[BZOJ4870/LOJ2143][Shoi2017]组合数问题

本文介绍了一种使用矩阵乘法优化动态规划的问题解决策略。通过将问题转化为在nk个物品中选择满足特定模条件的x个物品的方案数,文章详细阐述了如何构建状态转移方程,并利用矩阵快速幂进行高效求解。特别关注了k=1的特殊情况。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目链接:

BZOJ4870 LOJ2143

神仙思维题。

直接推式子是找不到什么性质的,我们来考虑一下这个式子的意义:

\(nk\)个物品中,选\(x(x\mod{k}\equiv r)\)个物品的方案数

那么可以DP:设\(f[i][j]\)表示前\(i\)个物品,选\(x(x\mod{k}\equiv j)\)个物品的方案数

则有:\(f[i][j]=f[i-1][(j-1)\mod{k}]+f[i-1][j]\)

那么就可以矩阵乘法优化了。

时间复杂度 \(O(k^2\log n)\)

注意特判\(k=1\)的情况

代码:

#include <cstdio>
#include <cstring>
#define rint register int
typedef long long ll;

int n,p,k,r;

struct Matrix
{
    int n,m,a[55][55];
    inline Matrix(int ns,int ms){n=ns,m=ms;memset(a,0,sizeof a);}

    inline Matrix operator*(const Matrix &o)const
    {
        Matrix Res(n,o.m);
        for(rint i=0;i<n;++i)
            for(rint k=0;k<m;++k)
                for(rint j=0;j<o.m;++j)
                    Res.a[i][j]=(Res.a[i][j]+(ll)a[i][k]*o.a[k][j])%p;
        return Res;
    }
};

int main()
{
    scanf("%d%d%d%d",&n,&p,&k,&r);
    Matrix f(1,k),g(k,k);
    f.a[0][0]=1;
    for(rint i=0;i<k;++i)++g.a[i][i],++g.a[i][(i+1)%k];//不直接赋值,防止k=1特殊情况
    for(ll b=(ll)n*k;b;b>>=1,g=g*g)if(b&1)f=f*g;
    printf("%d\n",f.a[0][r]);
    return 0;
}

转载于:https://www.cnblogs.com/LanrTabe/p/11496613.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值