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

P3746 [六省联考2017]组合数问题

时间:2018-12-27 15:29:04      阅读:145      评论:0      收藏:0      [点我收藏+]

标签:name   组合   char   using   max   struct   getc   mem   cstring   

P3746 [六省联考2017]组合数问题

\(dp_{i,j}\)表示前\(i\)个物品,取的物品模\(k\)等于\(r\),则\(dp_{i,j}=dp_{i-1,(j-1+k)%k}+dp_{i-1,j}\)

\(dp_{i,0},dp_{i,1},dp_{i,2}.....dp_{i,k-1}\) \(\Longrightarrow\) \(dp_{i+1,0},dp_{i+1,1},dp_{i+1,2}.....dp_{i+1,k-1}\)

仔细想想,你能构造出矩阵的

#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;
typedef long long LL;
const LL maxn=100;
inline LL Read(){
    LL x=0,f=1; char c=getchar();
    while(c<'0'||c>'9'){
        if(c=='-') f=-1; c=getchar();
    }
    while(c>='0'&&c<='9')
        x=(x<<3)+(x<<1)+c-'0',c=getchar();
    return x*f;
}
struct mat{
    LL m[maxn][maxn];
}rt,a,b;
LL n,MOD,K,r;
inline mat Mul(const mat &x,const mat &y){
    mat res;
    memset(res.m,0,sizeof(res.m));
    for(LL i=0;i<=K-1;++i)
        for(LL j=0;j<=K-1;++j)
            for(LL k=0;k<=K-1;++k)
                res.m[i][j]=(res.m[i][j]+x.m[i][k]*y.m[k][j]%MOD)%MOD;
    return res;
}
inline void Pow(LL mi){
    while(mi){
        if(mi&1)
            a=Mul(a,b);
        b=Mul(b,b);
        mi>>=1;
    }
}
int main(){
    n=Read(),MOD=Read(),K=Read(),r=Read();
    for(LL i=0;i<=K-2;++i)
        b.m[i][i]=b.m[i][i+1]=1;
    ++b.m[K-1][0],++b.m[K-1][K-1];
    for(LL i=0;i<=K-1;++i)
        a.m[i][i]=1;
    Pow(n*K);
    rt.m[0][0]=1;
    rt=Mul(rt,a);
    printf("%lld",rt.m[0][r]);
    return 0;
}

P3746 [六省联考2017]组合数问题

标签:name   组合   char   using   max   struct   getc   mem   cstring   

原文地址:https://www.cnblogs.com/y2823774827y/p/10184572.html

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