sgu197

来源:互联网 发布:java那地方做的不好 编辑:程序博客网 时间:2024/06/17 12:45

注意条件 m<=5,这告诉我们,对于每一列,状态数是很少的,所以怎么乱搞都可以
所以可以递推求解(注意是递推不是动归)。

f(i,S) 表示第 i 列状态为 S 的方案数,有 f(i,S)=f(i1,S) | S>S

用矩阵表示 Fi 表示第 i 列每种状态方案数的矩阵,Fi=TFi1,其中 T 为转移矩阵
所以 Fi=Tn1F1Tn1用快速幂解决即可。


另外 n 需要高精度运算。


#include<cstdio>#include<cstdlib>#include<cstring>#include<iostream>#include<algorithm>#define Get(i,j) (i&(1<<j))const int MAXM = 6;struct Matrix{int n ,m ,a[1<<5][1<<5];};struct BigNumber{    int l,num[1<<7];    void scan()    {        static char s[1<<7];        scanf("%s",s+1),l = strlen(s+1);        for(int i = 1; i <= l; i++)          num[i] = s[l-i+1] - '0';          }    BigNumber minus1()    {        --num[1];        for(int i = 1; i <= l; i++)           if(num[i] < 0) num[i] += 10, num[i+1]--;           else break;        if(!num[l]) l--;        return (*this);         }    BigNumber div2()    {        for(int i = 1; i <= l; i++)        {          if(num[i]&1) num[i-1]+=10>>1;          num[i] >>= 1;        }        if(!num[l]) l--;        return (*this);    }    int mod2()    {        return num[1]&1;    }    bool zero()    {        if(l) return false;        else return true;    }};BigNumber N;int M, p;Matrix I = {0};Matrix F = {0}, Ans = {0};int ans = 0;Matrix operator *(Matrix A,Matrix B){    Matrix C = {A.n,B.m,{0}};    for(int i = 0; i < A.n; i++)      for(int j = 0; j < B.m; j++)        for(int k = 0; k < A.m; k++)          C.a[i][j] = (C.a[i][j]+A.a[i][k]*B.a[k][j])%p;    return C;    }Matrix PowerMod(Matrix G,BigNumber k){    Matrix R = I;    while(!k.zero())    {        if(k.mod2()) R = R * G;        G = G * G, k = k.div2();    }    return R;}int main(){#ifndef ONLINE_JUDGE    freopen("sgu197.in","r",stdin);    freopen("sgu197.out","w",stdout);#endif    N.scan();    std::cin >> M >> p;    I.n = I.m = F.n = F.m = 1<<M;    for(int i = 0; i < I.n; i++)        I.a[i][i] = 1;    for(int i = 0; i < F.n; i++)      for(int j = 0; j < F.m; j++)      {        F.a[i][j] = 1;          for(int k = 1,a,b,c,d; k < M; k++)        {            a = Get(i,k-1), c = Get(i,k);            b = Get(j,k-1), d = Get(j,k);            if((a && b && c && d) || !(a || b || c || d))                 {F.a[i][j] = 0; break;}        }      }    Ans.n = 1<<M, Ans.m = 1;    for(int i = 0; i < Ans.n; i++)      Ans.a[i][0] = 1;    Ans = PowerMod(F,N.minus1()) * Ans;     for(int i = 0; i < Ans.n; i++)      ans += Ans.a[i][0], ans %= p;     std::cout << ans << std::endl;   #ifndef ONLINE_JUDGE    fclose(stdin);    fclose(stdout);#endif    return 0;}
0 0
原创粉丝点击