【Luogu】P3746组合数问题(矩阵)
哇我一个活人的智商被题目碾压了
可以把问题转化为有nk个物品,问拿i件物品的方案数有多少种,其中i%k=r。
然后矩阵乘法加速DP即可。
#include<cstdio> #include<cstdlib> #include<cstring> #include<algorithm> #include<cctype> #define maxn 55 using namespace std; inline long long read(){ long long num=0,f=1; char ch=getchar(); while(!isdigit(ch)){ if(ch=='-') f=-1; ch=getchar(); } while(isdigit(ch)){ num=num*10+ch-'0'; ch=getchar(); } return num*f; } int m;long long mod,n,r; struct Matrix{ long long s[maxn][maxn]; void clear(){memset(s,0,sizeof(s));} Matrix operator *(Matrix a){ Matrix ans; ans.clear(); for(int i=1;i<=m;++i) for(int j=1;j<=m;++j) for(int k=1;k<=m;++k) ans.s[i][j]=(ans.s[i][j]+s[i][k]*a.s[k][j]%mod)%mod; return ans; } }start,d; Matrix Pow(Matrix a,long long b){ Matrix ret; ret.clear(); for(int i=1;i<=m;++i) ret.s[i][i]=1; while(b){ if(b&1) ret=ret*a; a=a*a; b>>=1; } return ret; } int main(){ start.clear(); n=read();mod=read();m=read();r=read(); //start.s[1][m]=1; for(int i=1;i<=m;++i) start.s[i][i]++,start.s[(i-2+m)%m+1][i]++; n*=m; start=Pow(start,n); d.s[1][1]=1; d=d*start; printf("%lld\n",d.s[1][r+1]); return 0; }