BZOJ 4870 [Shoi2017]组合数问题

题解:

解题思路,发现式子的意义。

从nk个物品中选出%k为r个物品的方案数

然后DP

 

然后用矩阵快速幂加速

注意k==0的情况!!!

 

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int maxn=60;
typedef long long Lint;
int mm;
int n,m,r;

struct Mat{
	Lint arr[maxn][maxn];
	Mat(){
		memset(arr,0,sizeof(arr));
	}
	void Clea(){
		memset(arr,0,sizeof(arr));
	}
	void MakeE(){
		memset(arr,0,sizeof(arr));
		for(int i=0;i<m;++i)arr[i][i]=1;
	}
}Mx,My,Mz,Ma,Mret;

void Mul(){
	Mz.Clea();
	for(int i=0;i<m;++i){
		for(int j=0;j<m;++j){
			for(int k=0;k<m;++k){
				Mz.arr[i][j]=(Mz.arr[i][j]+Mx.arr[i][k]*My.arr[k][j])%mm;
			}
		}
	}
}

void Ksm(Lint p){
	Mret.MakeE();
	for(;p;p>>=1){
		if(p&1){
			Mx=Ma;My=Mret;Mul();Mret=Mz;
		}
		Mx=Ma;My=Ma;Mul();Ma=Mz;
	}
}

int main(){
	scanf("%d%d%d%d",&n,&mm,&m,&r);
	for(int i=0;i<m;++i){
		Ma.arr[i][(i-1+m)%m]++;
		Ma.arr[i][i]++;
	}
	Ksm(1LL*n*m-1);
	printf("%lld\n",(Mret.arr[r][0]+Mret.arr[r][1%m])%mm);
	return 0;
}

 

  

 

转载于:https://www.cnblogs.com/zzyer/p/8560590.html

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值