标签:return lld 贪心 name ++ 个性 一个 证明 cst
对于 100% 的数据,满足 0<=N, M<=10^12 ,N*M<=10^12。
题解:Lucas定理+贪心
先打出个表来,发现c数组就是杨辉三角嘛(只不过45°的放在数组里。
然后(x,y)的C值,就是组合数C(x+y,y)。
那么对于点n,m,先沿着(0,0)-->(1,0)-->(2.0)--...-->(n,0)
然后(n,1)-->(n,2)-->(n,3)--...(n,m),表上看出C(n,m)=C(m,n),(这个C是价值
然后用Lucas求组合数就可以啦。
其实本来想做费马小定理来着...
在Lucas求逆元中,n!/(m!*(n-m)!)==> n!*(m!*(n-m)在mod数意义下的逆元)
由欧拉定理知道a^(phi(n))≡1(mod n)当a,n互质时,费马小定理为当n为质数时
a^(phi(n))=a^(n-1)≡1(mod n),那么a关于MOD n意义下的逆元就是a^(n-2)。
假设n>m(让竖着走的1多一点
那么答案就是n+sigma(i=0--m)C(n+i,i)
sigma那个是 C(n+m+1,m)。
这个我不会证.....才怪 略略略
证明:C(n,0)+C(n+1,1)+C(n+2,2)+C(n+2,3)+....+C(n+m,m)
额...不会 推荐播客
代码:
最近Lucas定理做的太多了...不做了.... 感觉这个题的数据范围有点玄....
#include<iostream> #include<cstdio> #include<cstring> #define LL long long using namespace std; const LL mod=1e9+7; LL m,n; LL ksm(LL x,LL y){ LL ret=1; while(y){ if(y&1)ret=ret*x%mod; x=x*x%mod; y>>=1; } return ret; } LL C(LL n,LL m){ if(m>n)return 0; LL s1=1,s2=1; for(LL i=n-m+1;i<=n;i++)s1=s1*i%mod; for(LL i=1;i<=m;i++)s2=s2*i%mod; return s1*ksm(s2,mod-2); } LL Lucas(LL n,LL m){ if(!m)return 1; return C(n%mod,m%mod)*Lucas(n/mod,m/mod)%mod; } int main(){ scanf("%lld%lld",&n,&m); printf("%lld\n",(max(n,m)%mod+Lucas(n+m+1,min(n,m))%mod)%mod); return 0; }
标签:return lld 贪心 name ++ 个性 一个 证明 cst
原文地址:http://www.cnblogs.com/zzyh/p/7669966.html