打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
[SDOI2010]古代猪文

题解:

一看就是一道数学题了。

根据欧拉定理,必须要处理的是$sum_i|n C(n,i)\space mod \space \phi(p)$

令A等于这个大式子。

phi(p)=999911658=2*3*4679*35617

是四个质数的乘积。

看来就类似扩展LUCAS了。

但是,指数只有1

所以,我们可以求出:

A = a1 mod 2

A = a2 mod 3

A = a3 mod 4679

A = a4 mod 35617

(a1~a4怎么求?LUCAS定理即可。)

这是一个同余方程,要解出A

其实,我们就要A = a5 mod 999911658

中国剩余定理合并,返回a5即可。

不会CRT?右转:CRT&EXCRT 中国剩余定理及其扩展

注意,求的A是在mod 999911658下的。不能用其他质数mod完。除了ti,即Mi在mod mi下的逆元。

 

最后计算G^a5 mod 999911659

但是,出题人比较狡诈,还是有坑的。

因为,欧拉定理的适用的前提是:gcd(G,mod)=1;

扩展欧拉定理更是如此。

如果G=mod,那么就不互质了。

如果这时候,恰好a5=0,那么我们会输出1

其实答案无论如何是0

G=mod判掉即可。

 

代码:

#include<bits/stdc  .h>using namespace std;typedef long long ll;const int N=35666;const int mod=999911659;const int P[4]={2,3,4679,35617};ll jie[4][N],inv[4][N];ll f[4][2];ll n,g;ll qm(ll x,ll y,ll p){    ll ret=1%p;    while(y){        if(y&1) (ret*=x)%=p;        (x*=x)%=p;        y>>=1;    }    return ret;}ll C(ll a,ll b,ll id){    //if(b==0) return 1;    ll ret=jie[id][a]*inv[id][a-b]%P[id]*inv[id][b]%P[id];    //cout<<" C "<<a<<" "<<b<<" "<<id<<" "<<P[id]<<" : "<<jie[id][a]<<" "<<inv[id][a-b]<<" "<<inv[id][b]<<" "<<ret<<endl;    return ret;}ll Lucas(ll a,ll b,ll id){    if(a<b) return 0;    if(a<P[id]) return C(a,b,id);    return (Lucas(a%P[id],b%P[id],id)*Lucas(a/P[id],b/P[id],id))%P[id];}ll merge(){//ret x%phi(mod)    ll phi=mod-1;    ll ret=0;    for(int i=0;i<4;i  ){        ll cheng=1;        for(int j=0;j<4;j  ){            if(i==j) continue;            cheng*=P[j];        }        ll iv=qm(cheng%P[i],P[i]-2,P[i]);        cheng=(cheng*f[i][1]%phi*iv%phi);        (ret =cheng)%=phi;    }    return ret;}int fac[100001],tot;void divi(){    for(int i=1;(ll)i*i<=n;i  ){        if(n%i==0){            fac[  tot]=i;            if(i!=n/i) fac[  tot]=n/i;        }    }}int main(){    scanf("%lld%lld",&n,&g);    if(g==mod){        printf("0");return 0;    }    divi();    //cout<<tot<<endl;    //for(int i=1;i<=tot;i  ) cout<<fac[i]<<" ";cout<<endl;    for(int i=0;i<4;i  ){        jie[i][0]=1;        inv[i][0]=1;        for(int j=1;j<P[i];j  ){            jie[i][j]=(jie[i][j-1]*j)%P[i];            inv[i][j]=qm(jie[i][j],P[i]-2,P[i]);        }        ll sum=0;        for(int j=1;j<=tot;j  ){            (sum =Lucas(n,fac[j],i))%=P[i];            //cout<<" j "<<fac[j]<<" "<<sum<<endl;        }        //cout<<i<<" "<<P[i]<<" : "<<sum<<endl;        f[i][0]=P[i];        f[i][1]=sum;    }    //cout<<jie[2][3]<<" "<<qm(6,P[2]-1,P[2])<<" "<<inv[2][3]<<endl;    //cout<<Lucas(4,4,0)<<endl;    ll mi=merge();    ll ans=qm(g,mi,mod);    printf("%lld",ans);    return 0;}/*   Author: *Miracle*   Date: 2018/10/2 20:41:08*/

 

来源:http://www.icode9.com/content-4-34651.html
本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
P4007 小 Y 和恐怖的奴隶主
常用矩阵计算C语言代码
NOIP训练营内部试题-棋盘问题
L1-008 求整数段和 (10分)
178 f0602
在Visual C++ 6.0上实现矩阵的各种运算
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服