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

Posted invictus-ocean

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了六省联考2017组合数问题 题解(矩阵快速幂优化DP)相关的知识,希望对你有一定的参考价值。

题目链接

题目大意:求$(sumlimits_{i=0}^n C_{nk}^{ik+r}) mod p$的值。

---------------------

讲真,一开始看到这个题我都没往DP方面想,以为是什么大力推式子的数学题。

设$f_{i,j}$表示考虑前$i$个物品,选出的物品$mod k=j$的方案数。最后输出$f_{n,r}$。

易得转移方程:

$f_{i,j}=f_{i-1,j}+f_{i-1,j-1}$

$f_{i,0}=f_{i-1,0}+f_{i-1,k-1}$

看到数据范围想到矩阵加速,有转移矩阵:

$egin{bmatrix}1&0&cdots&0&1\1&1&0&cdots&0\0&1&1&cdots&0\vdots&ddots&ddots&ddots&vdots\0&0&cdots&1&1 end{bmatrix}$

矩阵快速幂乘$nk$次方即可。

注意当$k=1$时只有一个元素,其初始值为2。

代码:

#include<bits/stdc++.h>
#define int long long
using namespace std;
int n,p,k,r;
struct node
{
    int a[55][55];
    node(){
        memset(a,0,sizeof(a));
    }
    inline void build(){
        for (int i=1;i<=k;i++) a[i][i]=1;
    }
};
node operator * (const node x,const node y)
{
    node z;
    for (int l=1;l<=k;l++)
        for (int i=1;i<=k;i++)
            for (int j=1;j<=k;j++)
                z.a[i][j]=(z.a[i][j]+x.a[i][l]*y.a[l][j])%p;
    return z;
}
signed main()
{
    cin>>n>>p>>k>>r;int mi=n*k;
    node a,ans;ans.build();
    for (int i=1;i<=k-1;i++) a.a[i][i]++,a.a[i][i+1]++;
    a.a[k][1]++,a.a[k][k]++;
    while(mi)
    {
        if (mi&1) ans=ans*a;
        a=a*a;
        mi>>=1;
    }
    printf("%lld",ans.a[k][k-r]);
    return 0;
}

 

以上是关于六省联考2017组合数问题 题解(矩阵快速幂优化DP)的主要内容,如果未能解决你的问题,请参考以下文章

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

六省联考:组合数问题

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

[六省联考2017]相逢是问候(扩展欧拉定理+预处理幂)

[六省联考2017]期末考试 贪心 枚举

[六省联考2017]分手是祝愿 题解(期望dp)