菜菜的喵喵题~
化序列为矩阵!化腐朽为神奇!左上角为1,往右每次*3,往下每次*2,这样子就把问题转化成了在矩阵里选不相邻的数有几种可能。
举个矩阵的例子
1 3 9 27
2 6 18 54
4 12 36 108
这样最多11列,最多17行,那么方案数就可以用状压了。
但是我们会发现,矩阵里没有5,所以我们要把5作为左上角再算一次答案,最后把所有矩阵的答案用乘法原理乘起来就好
#include<iostream> #include<cstring> #include<cstdlib> #include<cstdio> #include<cmath> #include<algorithm> #define MOD(x) ((x)>=mod?(x)-mod:(x)) using namespace std; const int maxn=500010,mod=1e9+1; int n,ans,cnth; int f[20][1<<11],cntl[20]; bool v[maxn]; inline void read(int &k) { int f=1;k=0;char c=getchar(); while(c<'0'||c>'9')c=='-'&&(f=-1),c=getchar(); while(c<='9'&&c>='0')k=k*10+c-'0',c=getchar(); k*=f; } inline int find(int x) { cnth=0;memset(cntl,0,sizeof(cntl)); for(int i=1,fir=x;fir<=n;i++,fir*=2,cnth++) for(int j=1,sec=fir;sec<=n;j++,sec*=3,cntl[i]++)v[sec]=1; f[0][0]=1; for(int i=1;i<=cnth;i++)for(int j=0;j<=(1<<cntl[1])-1;j++)f[i][j]=0; for(int i=1;i<=cnth;i++) for(int j=0;j<(1<<cntl[i]);j++) if(!(j&(j>>1))) for(int k=0;k<(1<<cntl[i-1]);k++) if(!(k&(k>>1)))if(!(j&k))f[i][j]=MOD(f[i][j]+f[i-1][k]); int sum=0; for(int i=0;i<=(1<<cntl[cnth])-1;i++)sum=MOD(sum+f[cnth][i]); return sum; } int main() { read(n);ans=1; for(int i=1;i<=n;i++) if(!v[i])ans=1ll*ans*find(i)%mod; printf("%d ",ans); }