bzoj 3738: [Ontak2013]Kapitał 数论

来源:互联网 发布:百分百邮件营销软件 编辑:程序博客网 时间:2024/06/05 15:34

       首先orz PoPoQQQ

       不过后来想了一下好像不用crt合并那么麻烦。。。注意到当n>s时(s是一个很小的常数,应该在20~30左右),显然有n!的2的次数远远大于5的次数。那么这时5被2完全抵消之后,必然有2的次数>9,因此mod 512显然=0。那么大概就可以少一半的工作量啦?

       不管了反正我抄Po爷代码。。

AC代码如下:

#include<iostream>#include<cstdio>#include<cstring>#define ll long long#define mod1 512#define mod2 1953125using namespace std; struct node{ ll x,y; }; ll n,m,k,pow1[2000005],pow2[2000005];ll ksm(ll x,ll y,ll p){    ll t=1; for (; y; y>>=1,x=x*x%p) if (y&1) t=(ll)t*x%p;    return t;}node tms(node u,node v,ll p){    return (node){u.x*v.x%p,u.y+v.y};}node dvd(node u,node v,ll p,ll phi){    return (node){u.x*ksm(v.x,phi-1,p)%p,u.y-v.y};}node fct(ll x,ll p,ll q,ll *pw){    if (!x) return (node){1,0};    ll t=ksm(pw[q],x/q,q)*pw[x%q]%q;    return tms((node){t,x/p},fct(x/p,p,q,pw),q);}void write(ll x,ll k){    if (!k) return; write(x/10,k-1);    printf("%lld",x%10);}int main(){    scanf("%lld%lld%lld",&m,&n,&k);    pow1[0]=pow2[0]=1; int i;    for (i=1; i<=mod1; i++) pow1[i]=pow1[i-1]*((i&1)?i:1)%mod1;    for (i=1; i<=mod2; i++) pow2[i]=pow2[i-1]*((i%5)?i:1)%mod2;    node u=fct(m+n,2,mod1,pow1);    u=dvd(u,fct(m,2,mod1,pow1),mod1,mod1>>1);    u=dvd(u,fct(n,2,mod1,pow1),mod1,mod1>>1);    node v=fct(m+n,5,mod2,pow2);    v=dvd(v,fct(m,5,mod2,pow2),mod2,(mod2/5)<<2);    v=dvd(v,fct(n,5,mod2,pow2),mod2,(mod2/5)<<2);    ll t=min(u.y,v.y);    ll x=u.x*ksm(2,u.y-t,mod1)%mod1*ksm(205,t,mod1)%mod1;    ll y=v.x*ksm(5,v.y-t,mod2)%mod2*ksm(976563,t,mod2)%mod2;    ll ans=(x*212890625+y*787109376)%1000000000;    write(ans,k);    return 0;}


by lych

2016.4.22

0 0