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

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

转载于:https://www.cnblogs.com/y2823774827y/p/10184572.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值