注意条件 m<=5,这告诉我们,对于每一列,状态数是很少的,所以怎么乱搞都可以。
所以可以递推求解(注意是递推不是动归)。
f(i,S) 表示第 i 列状态为 S 的方案数,有 f(i,S)=∑f(i−1,S′) | S′−>S
用矩阵表示 :Fi 表示第 i 列每种状态方案数的矩阵,Fi=T∗Fi−1,其中 T 为转移矩阵
所以 Fi=Tn−1∗F1, Tn−1用快速幂解决即可。
另外 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;
}
版权声明:本文为博主原创文章,未经博主允许不得转载。