为了1A我居然写了个暴力对拍...
那个式子本质上是求nk个数里选j个数,且j%k==r的方案数。
所以把组合数的递推式写出来f[i][j]=f[i-1][j]+f[i-1][(j-1+k)%k]...我们知道求组合数实际上是可以矩阵乘法优化的,只是没必要,但是这个时候就用上了...
于是矩阵乘法优化,AC之~
#include<iostream> #include<cstring> #include<cstdlib> #include<cstdio> #include<algorithm> #define ll long long #define MOD(x) ((x)>=p?(x)-p:(x)) using namespace std; const int maxn=310,inf=1e9; typedef ll mtx[60][60]; int n,p,K,r; mtx f,g; 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; } void mul(mtx &a,mtx b) { mtx c;memset(c,0,sizeof(c)); for(int i=1;i<=K;i++) for(int j=1;j<=K;j++) for(int k=1;k<=K;k++) c[i][j]=(c[i][j]+a[i][k]*b[k][j])%p; memcpy(a,c,sizeof(c)); } void power(ll b) { for(;b;mul(f,f),b>>=1) if(b&1)mul(g,f); } int main() { read(n);read(p);read(K);read(r); for(int i=1;i<=K;i++)g[i][i]=1,f[i][i]=1; for(int i=1;i<=K;i++)f[i][(i-2+K)%K+1]++; power(1ll*n*K); printf("%lld ",g[r+1][1]); }