(组合数问题)牛客网Wannafly挑战赛17 B题 求值2

链接:https://www.nowcoder.com/acm/contest/114/B
来源:牛客网
 

时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 262144K,其他语言524288K
64bit IO Format: %lld

题目描述

Ans = 0; 
For(inti = 1; i <= n; i++) 
    For(int v = 0; v <= n; v++) 
        Ans = (Ans + C(i, v) * C(i, v)) % 998244353;

C(i,v)为组合数第i行第v列的数。
给你上面的代码中的n,请你输出Ans的值。

输入描述:

输入一个整数n

输出描述:

输出Ans的值。

示例1

输入

复制

3

输出

复制

28

备注:

n<=106

首先C(i,v)组合数中,v必定小于i,所以v的范围是[0,i]。对于每个i我们需要计算C(i,0)+C(i,1)+........C(i,i)。这个式子有个公式等于C(2i,i)。那么对于每个i我们需要将这个组合数相加,我们需要计算C(2,1)+C(4,2)+.....C(2n,n)   

我们根据公式推导,发现C(2i,i)=C(2(i-1),i-1)*(4i-2)/i%mod,所以我们只需要用一个循环就能表达这个式子。

但这个时候我们发现,除以i之后再取模和取模之后再除i结果是不一样的。这就涉及到了逆元的问题,a/b%(mod)=a*b^(-1)%mod     其中 b^(-1)就是b的逆元。

根据费马小定理 a^p=a mod p    (前提a是整数,p是素数)   如果a不是p的整数倍 a^(p-1)=1 mod p  

我们令 c=b^(-1)   c*b=1 mod p=b^(p-1)  ,所以 c 可以写成 b^(p-2) mod p。那么推导式为:

C(2i,i)=C(2(i-1),i-1)*(4i-2)*i^(mod-2)%mod 这样计算式中都是乘法就不存在除法的问题以下为源代码。

#include<stdio.h>
#include<string.h>

#define mod 998244353

int qpow(long long b,int m){
	long long sum=1;
	
	while(m){
		if(m%2) sum=sum*b%mod;
		m=m/2;
		b=b*b%mod;
	}
	return sum;
}

int main(){
	int i,n;
	long long b,a,m2;
	
	while(scanf("%d",&n)!=EOF){
		b=0;
		a=1;
		for(i=1;i<=n;i++){
			a=a*(4*i-2)%mod;
			m2=qpow(i,mod-2);
			a=a*m2%mod;
			b=(b+a)%mod;	
		}
		printf("%lld\n",b);
	}	
	
	return 0;
}

猜你喜欢

转载自blog.csdn.net/ACM5100/article/details/80739255