码迷,mamicode.com
首页 > 其他好文 > 详细

六省联考2017 组合数问题

时间:2018-02-24 19:27:56      阅读:212      评论:0      收藏:0      [点我收藏+]

标签:main   int   i++   lan   names   freopen   转移   span   namespace   

题链

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;
}

 

六省联考2017 组合数问题

标签:main   int   i++   lan   names   freopen   转移   span   namespace   

原文地址:https://www.cnblogs.com/rrsb/p/8467054.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!