链接: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;
}