六省联考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;
}

 

posted @ 2018-02-24 17:25  泪寒之雪  阅读(391)  评论(0编辑  收藏  举报