您的位置:首页 > 其它

[BZOJ4870][SHOI2017]组合数问题 DP+矩阵快速幂

2017-11-01 07:53 537 查看
考虑这个式子的组合意义,表示从nk个物品中选取mod k=r个物品。递推式很显然咯,f[i][j]=f[i-1][j]+f[i-1][(j-1)%k]。矩阵快速幂加速一下就好了。

WA点:转移矩阵第i行是第j列和(j-1)%k列为一,所以第0行是第0列和k-1列,特别地,当k=1时,1*1矩阵中那个唯一的数应该是2,因为加了两次。

代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#define ll long long
using namespace std;
ll n,r,K,mod;
struct matrix
{
ll a[51][51];
matrix(){memset(a,0,sizeof(a));}
matrix operator *(const matrix &x)
{
matrix ans;
for(int i=0;i<K;i++)
for(int j=0;j<K;j++)
for(int k=0;k<K;k++)
ans.a[i][j]=(ans.a[i][j]+a[i][k]*x.a[k][j]%mod)%mod;
return ans;
}
}m;
matrix ksm(matrix a,ll b)
{
matrix re;
for(int i=0;i<K;i++) re.a[i][i]=1;
for(;b;b>>=1)
{
i
fa97
f(b&1) re=re*a;
a=a*a;
}
return re;

}
int main()
{
scanf("%lld%lld%lld%lld",&n,&mod,&K,&r);
m.a[0][0]+=1;m.a[0][K-1]+=1;
for(int i=1;i<K;i++)
m.a[i][i]=m.a[i][i-1]=1;
m=ksm(m,n*K);
printf("%lld",m.a[0][r]);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: