bzoj 4563: [Haoi2016]放棋子 动态规划

来源:互联网 发布:ps4数码宝贝网络侦探 编辑:程序博客网 时间:2024/05/20 18:03

题意

给你一个N*N的矩阵,每行有一个障碍,数据保证任意两个障碍不在同一行,任意两个障碍不在同一列,要求你在
这个矩阵上放N枚棋子(障碍的位置不能放棋子),要求你放N个棋子也满足每行只有一枚棋子,每列只有一枚棋子
的限制,求有多少种方案。
n<=200

分析

恩由于是算方案数,所以可以将所有障碍移到对角线上,然后就很神奇地变成了一个错排问题。。。
递推式是f[i]=(f[i-1]+f[i-2])*(i-1)
需要高精度。

代码

#include<iostream>#include<cstdio>#include<cstdlib>#include<cstring>#include<algorithm>using namespace std;typedef long long LL;const int N=205;const int maxd=1000;LL a[maxd+5],b[maxd+5],c[maxd+5];void add(){    int g=0,s;    for (int i=maxd;i>=1;i--)    {        s=a[i]+b[i]+g;        c[i]=s%10;        g=s/10;    }}void mul(int x){    int g=0,s;    for (int i=maxd;i>=1;i--)    {        s=c[i]*x+g;        c[i]=s%10;        g=s/10;    }}int main(){    int n;    scanf("%d",&n);    for (int i=1;i<=n;i++)        for (int j=1;j<=n;j++)        {            int x;            scanf("%d",&x);        }    a[maxd]=c[maxd]=1;    for (int i=3;i<=n;i++)    {        add();        mul(i-1);        for (int j=maxd;j>=1;j--) b[j]=a[j],a[j]=c[j];    }    int i=1;    while (!c[i]) i++;    for (int j=i;j<=maxd;j++) printf("%d",c[j]);    return 0;}
0 0