[codeforces 1288C] Two Arrays 动归dp/多重集合的组合+快速幂+乘法逆元

[codeforces 1288C] Two Arrays 动归dp/多重集合的组合+快速幂+乘法逆元

总目录详见https://blog.csdn.net/mrcrack/article/details/103564004

在线测评地址https://codeforces.com/contest/1288/problem/C

方法一:动归dp

Problem Lang Verdict Time Memory
C - Two Arrays GNU C++11 Accepted 15 ms 0 KB

此文https://www.cnblogs.com/Vampire6/p/12198070.html思路不错,摘抄如下
思路:用动态规划,dp[i][j]是第i个位置放数字j的方案数,根据题意可以将b数组反置然后接在a后面,则该数组长度为2m,为一个非递减序列,则就是求1~n这些数字可重复组成多少种长度为2m的非递减序列,可发现在第i位置放j-1必然在第i-1位置放j数字,所以可以得出状态方程dp[i][j]=dp[i-1][j]+dp[i][j-1].

#include <stdio.h>
#define mod 1000000007
int dp[25][1010];
int main(){
	int n,m,i,j,ans=0;
	scanf("%d%d",&n,&m);
	for(i=1;i<=n;i++)dp[1][i]=1;
	for(i=2;i<=2*m;i++)
		for(j=1;j<=n;j++)
			dp[i][j]=(dp[i][j-1]+dp[i-1][j])%mod;
	for(i=1;i<=n;i++)ans=(ans+dp[2*m][i])%mod;
	printf("%d\n",ans);
	return 0;
}

方法二:多重集合的组合+快速幂+乘法逆元

Problem Lang Verdict Time Memory
C - Two Arrays GNU C++11 Accepted 15 ms 0 KB

翻书,竟然是例题改编

 根据题意可以将b数组反置然后接在a后面,则该数组长度为2m,为一个非递减序列

若跟书学习觉得困难,可以跟随https://v.youku.com/v_show/id_XMTU2NzU2MDA4.html?spm=a2h0j.11185381.listitem_page1.5!10~A&&f=4253003视频,进行学习,学习内容如下

06:03-12:00 讲解了 多重集合的组合 公式的由来,关于这个公式,曾经弄懂过,但又很快不懂了,花了相当长的时间,从未真正弄懂过,真是踏破铁鞋无觅处,得来全不费工夫,今天,真正弄明白了,讲解肯定比看书好。一块心病,今天解决。2018-7-21 20:31

若对该书有兴趣,更多学习内容可参看文章https://blog.csdn.net/mrcrack/article/details/80562324

该题也即为求组合数C(2m+n-1,2m)

#include <stdio.h>
#define LL long long
#define mod 1000000007
int n,m;
LL quick_pow(LL a,int n){
	LL ret=1;
	while(n){
		if(n&1)ret=ret*a%mod;
		a=a*a%mod;
		n/=2;
	}
	return ret;
}
int main(){
	int i;
	LL ans=1,b=1;
	scanf("%d%d",&n,&m);
	for(i=2*m+n-1;i>=(2*m+n-1)-2*m+1;i--)ans=ans*i%mod;
	for(i=2*m;i>=1;i--)b=b*i%mod;
	printf("%lld\n",ans*quick_pow(b,mod-2)%mod);
	return 0;
}
发布了487 篇原创文章 · 获赞 516 · 访问量 43万+

猜你喜欢

转载自blog.csdn.net/mrcrack/article/details/103995362