暴力:
正解:
考虑循环矩阵,f[i][j]表示从i点到j点的方案数
我们发现n很小,我们预处理出n次的f[i][j]
然后在矩阵快速幂中,我们要从当前的f[i][j]*f[j][k]-->fir[i][j]
但是此时的循环为三层
我们考虑转移式子的意义在0-n次从i-j,在n+1到2×n转移至j
这样此时的j-k其实可以把他看作从0开始走j-k步本质上是一样的
然后还有一个特判,就不讲了
for(int j=0;j<n;++j) { ff[now][j]=(ff[now][j]+ff[last][((j-i)+n)%n])%mod; if((((j-i)+n)%n)==(j+i)%n)continue; ff[now][j]=(ff[now][j]+ff[last][(j+i)%n])%mod; }
代码
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 #include<bits/stdc++.h> 2 #define int long long 3 #define MAXN 4001 4 using namespace std; 5 int c[MAXN],f[MAXN],fir[MAXN]; 6 int n,m; 7 const int mod=1e9+7; 8 void cheng(int k) 9 { 10 memset(c,0,sizeof(c)); 11 if(k==1) 12 { 13 for(int i=0;i<n;++i) 14 { 15 for(int j=0;j<n;++j) 16 { 17 c[(i+j)%n]=(c[(i+j)%n]+f[j]*f[i]+mod)%mod; 18 //if(i*2==(j+i)%n)continue; 19 } 20 } 21 for(int i=0;i<n;++i)f[i]=c[i]%mod; 22 } 23 else 24 { 25 for(int i=0;i<n;++i) 26 { 27 for(int j=0;j<n;++j) 28 { 29 c[(i+j)%n]=(c[(i+j)%n]+fir[j]*f[i]+mod)%mod; 30 //if(i*2==((j+i)%n))continue; 31 } 32 } 33 for(int i=0;i<n;++i)fir[i]=c[i]%mod; 34 } 35 } 36 void poww(int y) 37 { 38 fir[0]=1ll; 39 while(y) 40 { 41 if(y&1ll)cheng(2ll); 42 cheng(1ll); 43 y>>=1ll; 44 } 45 } 46 int ff[4ll][MAXN];int g[MAXN]; 47 int now,last;int ans[MAXN]; 48 signed main() 49 { 50 //freopen("text.in","r",stdin); 51 //freopen("1.out","w",stdout); 52 scanf("%lld%lld",&n,&m); 53 int now=1;int last=0; 54 ff[0][0]=1; 55 for(int i=1;i<=n;++i) 56 { 57 if(i>1) 58 { 59 swap(now,last);memset(ff[now],0,sizeof(ff[now])); 60 } 61 for(int j=0;j<n;++j) 62 { 63 ff[now][j]=(ff[now][j]+ff[last][((j-i)+n)%n])%mod; 64 if((((j-i)+n)%n)==(j+i)%n)continue; 65 ff[now][j]=(ff[now][j]+ff[last][(j+i)%n])%mod; 66 } 67 if(i==m%n) 68 { 69 for(int j=0;j<n;++j) 70 { 71 g[j]=ff[now][j]%mod; 72 } 73 } 74 if(i==m) 75 { 76 printf("%lld\n",ff[now][0]); 77 return 0; 78 } 79 } 80 for(int i=0;i<n;++i) 81 { 82 f[i]=ff[now][i]%mod; 83 } 84 poww(m/n); 85 for(int i=0;i<n;++i) 86 { 87 for(int j=0;j<n;++j) 88 { 89 //if(i*2==((j+i)%n))continue; 90 ans[(i+j)%n]=(ans[(i+j)%n]+(g[i]*fir[j])%mod+mod)%mod; 91 } 92 } 93 if(m%n) 94 printf("%lld\n",ans[0]%mod); 95 else printf("%lld\n",fir[0]%mod); 96 }