bzoj4563 HAOI2016放旗子

bzoj传送门
已知了"任意两个障碍不在同一行,任意两个障碍不在同一列",如果我们按每列只能放一个来考虑,那么这\(n\)个障碍一定是一个排列,那么也就是“每一列只能放一个,有\((n-1)\)个位置可以放,每一列不能放的位置都不同”,很轻易可以想到错排问题(\(n\)个位置,每个位置上的数不能为位置的编号),本质相同,直接套错排问题求解即可。由于答案过大,我们考虑对……抱歉,此题没有模数,请自觉写高精度。
代码:

#include<cstdio>
#include<cstring>
#define max(a,b) (a>b?a:b)
int n,mp,pps=1000;
struct Bignum {
    int num[104];
    void clear() {
        memset(num,0,sizeof(num));
        num[0]=num[1]=1;
    }
    Bignum operator*(const int &a)const {
        Bignum c;memset(c.num,0,sizeof(c.num));
        c.num[0]=num[0];
        for(int i=1;i<=num[0];i++) {
            c.num[i]+=num[i]*a;
            c.num[i+1]+=c.num[i]/pps;
            c.num[i]%=pps;
        }
        if(c.num[c.num[0]+1])c.num[0]++;
        return c;
    }
    Bignum operator+(const Bignum &a)const {
        Bignum c;memset(c.num,0,sizeof(c.num));
        c.num[0]=max(num[0],a.num[0]);
        for(int i=1;i<=c.num[0];i++) {
            c.num[i]+=num[i]+a.num[i];
            c.num[i+1]+=c.num[i]/pps;
            c.num[i]%=pps;
        }
        if(c.num[c.num[0]+1])c.num[0]++;
        return c;
    }
    void print() {
        printf("%d",num[num[0]]);
        for(int i=num[0]-1;i>0;i--)
            printf("%03d",num[i]);
    }
}a,b,c;
int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++)for(int j=1;j<=n;j++)scanf("%d",&mp);
    a.clear(),a.num[1]=0,b.clear();
    for(int i=3;i<=n;i++)c=(a+b)*(i-1),a=b,b=c;
    b.print();
}
posted @ 2018-11-26 19:28  蒟蒻--lichenxi  阅读(102)  评论(0编辑  收藏  举报