AtCoder Beginner Contest 156 D Bouquet 失之交臂 容斥原理+二项式定理+乘法逆元+快速幂+模后负数 多余担心

AtCoder Beginner Contest 156

AtCoder Beginner Contest 156 D Bouquet 失之交臂  容斥原理+二项式定理+乘法逆元+快速幂+模后负数   多余担心

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

在线测评地址https://atcoder.jp/contests/abc156/tasks/abc156_d

容斥原理+二项式定理+乘法逆元+快速幂+模后负数

算了第一组数据

C(4,2)=6,C(4,4)=1,ans=6+1=7

还可以这样算

C(4,0)+C(4,1)+C(4,2)+C(4,3)+C(4,4)-C(4,1)-C(4,3)-C(4,0)

=2^4-C(4,1)-C(4,3)-1

=16-4-4-1

=7

但是,一直担心2≤n≤10^9在算n!时会超时,想过卢卡斯定理,但是很遗憾modulo (10^9+7)

马上切换到下一题E,解决了E中大半问题,被卡住了,又重新切换回来。

很快编好,死马当活马医,提交,担心的是没有发生,没有超时,但又WA,看啦看只有一组数据出错,

收获n=10^9,n!的计算,既然消耗不到1s,打破了10^6-10^7需消耗1s的认知。多余担心

哪错了呢,看看题目,扫扫代码,没有问题啊。

比赛结束后,马上就想到了,还是  模后可能遇到负数,如何处理成正数

ans=(ans%mod+mod)%mod;//错写成ans=(ans+mod)%mod;

修改,提交,立马AC.失之交臂.教训,考虑到的细节,还是要在代码中仔细看看,是否能精确的实现。

#include <stdio.h>
#define mod 1000000007
#define LL long long
LL n,a,b;
LL quick_pow(LL a,LL b){
	LL ans=1;
	while(b){
		if(b&1)ans=ans*a%mod;
		a=a*a%mod;
		b>>=1;
	}
	return ans;
}
LL C(LL a,LL b){
	LL i,ans=1,c=1;
	for(i=a;i>=a-b+1;i--)ans=ans*i%mod;
	for(i=b;i>=1;i--)c=c*i%mod;
	return ans*quick_pow(c,mod-2)%mod;
}
int main(){
	LL ans=0;
	scanf("%lld%lld%lld",&n,&a,&b);
	ans+=quick_pow(2,n)-1;//全集
	ans-=C(n,a);
	ans-=C(n,b);
	ans=(ans%mod+mod)%mod;//错写成ans=(ans+mod)%mod;
	printf("%lld\n",ans);
	return 0;
}
发布了552 篇原创文章 · 获赞 531 · 访问量 44万+

猜你喜欢

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