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

Posted y2823774827y

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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;
}

以上是关于P3746 [六省联考2017]组合数问题的主要内容,如果未能解决你的问题,请参考以下文章

六省联考:组合数问题

六省联考2017组合数问题 题解(矩阵快速幂优化DP)

bzoj千题计划263:bzoj4870: [六省联考2017]组合数问题

[六省联考2017]相逢是问候

P3747 [六省联考2017]相逢是问候

[BZOJ4872][六省联考2017]分手是祝愿