BZOJ 4870 [Shoi2017]组合数问题
题解:
解题思路,发现式子的意义。
从nk个物品中选出%k为r个物品的方案数
然后DP
然后用矩阵快速幂加速
注意k==0的情况!!!
#include<iostream> #include<cstdio> #include<cstring> using namespace std; const int maxn=60; typedef long long Lint; int mm; int n,m,r; struct Mat{ Lint arr[maxn][maxn]; Mat(){ memset(arr,0,sizeof(arr)); } void Clea(){ memset(arr,0,sizeof(arr)); } void MakeE(){ memset(arr,0,sizeof(arr)); for(int i=0;i<m;++i)arr[i][i]=1; } }Mx,My,Mz,Ma,Mret; void Mul(){ Mz.Clea(); for(int i=0;i<m;++i){ for(int j=0;j<m;++j){ for(int k=0;k<m;++k){ Mz.arr[i][j]=(Mz.arr[i][j]+Mx.arr[i][k]*My.arr[k][j])%mm; } } } } void Ksm(Lint p){ Mret.MakeE(); for(;p;p>>=1){ if(p&1){ Mx=Ma;My=Mret;Mul();Mret=Mz; } Mx=Ma;My=Ma;Mul();Ma=Mz; } } int main(){ scanf("%d%d%d%d",&n,&mm,&m,&r); for(int i=0;i<m;++i){ Ma.arr[i][(i-1+m)%m]++; Ma.arr[i][i]++; } Ksm(1LL*n*m-1); printf("%lld\n",(Mret.arr[r][0]+Mret.arr[r][1%m])%mm); return 0; }
致歉:笔者已经意识到这是一篇几乎没有价值的文章,给您的阅读带来不好的体验,并且干扰了您的搜索环境,非常抱歉!