[bzoj4870][Shoi2017]组合数问题
来自FallDream的博客,未经允许,请勿转载,谢谢。
与sdoi2017那道题神似
用f[i]表示选出的数量膜k等于i的方案数,容易构造转移矩阵,复杂度k^3log(nk)
也可以构造一个生成函数 复杂度k^2log(nk)
理论上可以优化到klognlogk 但常数巨大。
#include<iostream> #include<cstdio> #define MN 50 using namespace std; inline int read() { int x = 0 , f = 1; char ch = getchar(); while(ch < '0' || ch > '9'){ if(ch == '-') f = -1; ch = getchar();} while(ch >= '0' && ch <= '9'){x = x * 10 + ch - '0';ch = getchar();} return x * f; } int n,p,k,r,A[MN+5],B[MN+5],C[MN+5]; void Mul(int*a,int*b) { for(int i=0;i<k;++i) if(a[i]) for(int j=0;j<k;++j) C[(i+j)%k]=(C[(i+j)%k]+1LL*a[i]*b[j])%p; for(int i=0;i<k;++i) a[i]=C[i],C[i]=0; } int main() { n=read();p=read();k=read();r=read(); A[0]=1;B[0]=1;++B[1%k]; for(long long K=1LL*n*k;K;K>>=1,Mul(B,B)) if(K&1) Mul(A,B); printf("%d\n",A[r]); return 0; }
FallDream代表秋之国向您问好!
欢迎您来我的博客www.cnblogs.com/FallDream