首页 > 代码库 > [组合数取模-逆元计算模板] zoj 3624 Count Path Pair
[组合数取模-逆元计算模板] zoj 3624 Count Path Pair
思路:
正难则反
//C(M+N,M)*C(Q+M-P,Q)-C(N+M-P,N)*C(M+Q,M);
代码:
#include"cstdlib" #include"cstdio" #include"cstring" #include"cmath" #include"stack" #include"algorithm" #include"iostream" using namespace std; #define ll long long #define mod 100000007 //C(M+N,M)*C(Q+M-P,Q)-C(N+M-P,N)*C(M+Q,M); ll inverse[100005]; ll power(ll a,ll b) //关于逆元 其实如果mod是素数 则b的逆元其实就是b^(mod-2) { ll ans=1; while(b) { if(b&1) ans=(ans*a)%mod; a=(a*a)%mod; b>>=1; } return ans; } ll exgcd(ll a,ll b,ll &x,ll &y) { if(b==0) { x=1; y=0; return a; } ll t,r=exgcd(b,a%b,x,y); t=x; x=y; y=t-a/b*y; return r; } ll get_inverse(ll a) //exgcd求逆元 { ll x,y; exgcd(a,mod,x,y); return (x%mod+mod)%mod; } ll fc(ll n,ll m) { /*ll t1,t2; //数据小的话直接乘起来最后求一次逆元快 t1=t2=1; for(ll i=n;i>m;i--) { t1=(t1*i)%mod; t2=(t2*(i-m))%mod; } return t1*get_inverse(t2)%mod;*/ ll ans=1; //如果数据比较大 先预处理会用到的逆元 然后每次都乘逆元 for(ll i=n; i>m; i--) { ans=(ans*i)%mod; ans=(ans*inverse[i-m])%mod; } return ans; } int main() { ll m,n,p,q; for(int i=1; i<=100000; i++) inverse[i]=power(i,mod-2); //预处理逆元 for(int i=1; i<=100000; i++) inverse[i]=get_inverse(i); //预处理逆元 while(scanf("%lld%lld%lld%lld",&m,&n,&p,&q)!=-1) { ll a,b,c,d,ans; a=fc(m+n,m); b=fc(q+m-p,q); c=fc(n+m-p,n); d=fc(m+q,m); ans=(a*b)%mod-(c*d)%mod; ans=(ans%mod+mod)%mod; printf("%lld\n",ans); } return 0; }
[组合数取模-逆元计算模板] zoj 3624 Count Path Pair
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。