六省联考2017 组合数问题
SOL: 可以把原题看做在n*k个数里选p个数且p%k=r,
有DP f[i][j]=f[i-1][j]+f[i-1][j-1]
矩阵快速幂加速转移即可。
#include<bits/stdc++.h> using namespace std; #define LL long long LL k,mod,n,r; struct node{ LL a[50][50]; inline node operator * (const node&u) { static node z; for(int i=0;i<k;i++) for(int j=0;j<k;j++) { z.a[i][j]=0; for(int b=0;b<k;b++) z.a[i][j]=(z.a[i][j]+a[i][b]*u.a[b][j]%mod)%mod; } return z; } void init() { memset(a,0,sizeof a);for (int i=0;i<k;i++) a[i][i]=1; } }a,e; node qsm(node p,LL y){ node anw; for (anw.init();y;y>>=1,p=p*p) if (y&1) anw=anw*p; return anw; } signed main() { // freopen("problem.in","r",stdin); // freopen("problem.out","w",stdout); scanf("%lld%lld%lld%lld",&n,&mod,&k,&r); e.a[0][0]=1; for (int i=0;i<k;i++) a.a[i?i-1:k-1][i]++,a.a[i][i]++; n*=k; e=e*qsm(a,n); printf("%lld\n",e.a[0][r]); return 0; }