<body> <center> <h1>1951: [Sdoi2010]古代猪文</h1> <span class="green">Time Limit: </span>1 Sec <span class="green">Memory Limit: </span>64 MB<br> <span class="green">Submit: </span>3897 <span class="green">Solved: </span>1772<br>[<a href="submitpage.php?id=1951">Submit</a>][<a href="problemstatus.php?id=1951">Status</a>][<a href="bbs.php?id=1951">Discuss</a>] </center><h2>Description</h2><div class="content"> <p> “在那山的那边海的那边有一群小肥猪。他们活泼又聪明,他们调皮又灵敏。他们自由自在生活在那绿色的大草坪,他们善良勇敢相互都关心……”<br> ——选自猪王国民歌 </p> <p> 好久好久之前,在山的那边海的那边的某片风水宝地曾经存在过一个猪王国。猪王国地理位置偏僻,实施的是适应当时社会的自给自足的庄园经济,不多与外界联系,商贸活动就更少了。所以也不多有其余动物知道这样一个王国。<br> 猪王国虽然不大,可是土地肥沃,屋舍俨然。若是必定要拿什么与之相比的话,那就只能是东晋陶渊明笔下的你们想象中的桃花源了。猪王勤政爱民,猪民安居乐业,邻里和气相处,国家秩序井然,经济欣欣向荣,社会和谐稳定。和谐的社会带给猪民们对工做火红的热情和对将来的粉色的憧憬。<br> 小猪iPig是猪王国的一个很普通的公民。小猪今年10岁了,在大肥猪学校上小学三年级。和大多数猪同样,他不是很聪明,所以常常遇到不少或者稀奇古怪或者旁人看来垂手可得的事情令他大伤脑筋。小猪后来参加了全猪信息学奥林匹克竞赛(Pig Olympiad in Informatics, POI),取得了不错的名次,最终保送进入了猪王国大学(Pig Kingdom University, PKU)深造。<br> 如今的小猪已经能用计算机解决简单的问题了,好比能用P++语言编写程序计算出A + B的值。这个“成就”已经成为了他津津乐道的话题。固然,不明真相的同窗们也开始对他另眼相看啦~ 小猪的故事就将今后展开,伴随你们两天时间,但愿你们可以喜欢小猪。<br> </p> <div>题目描述</div> <p> 猪王国的文明源远流长,博大精深。<br> iPig在大肥猪学校图书馆中查阅资料,得知远古时期猪文文字总个数为N。固然,一种语言若是字数不少,字典也相应会很大。当时的猪王国国王考虑到若是修一本字典,规模有可能远远超过康熙字典,花费的猪力、物力将难以估量。故考虑再三没有进行这一项劳猪伤财之举。固然,猪王国的文字后来随着历史变迁逐渐进行了简化,去掉了一些不经常使用的字。<br> iPig打算研究古时某个朝代的猪文文字。根据相关文献记载,那个朝代流传的猪文文字刚好为远古时期的k分之一,其中k是N的一个正约数(能够是1和N)。不过具体是哪k分之一,以及k是多少,因为历史过于久远,已经无从考证了。<br> iPig以为只要符合文献,每一种能整除N的k都是有可能的。他打算考虑到全部可能的k。显然当k等于某个定值时,该朝的猪文文字个数为N / k。然而从N个文字中保留下N / k个的状况也是至关多的。iPig预计,若是全部可能的k的全部状况数加起来为P的话,那么他研究古代文字的代价将会是G的P次方。<br> 如今他想知道猪王国研究古代文字的代价是多少。因为iPig以为这个数字多是天文数字,因此你只须要告诉他答案除以999911659的余数就能够了。<br> </p> </div><h2>Input</h2><div class="content">有且仅有一行:两个数N、G,用一个空格分开。 </div><h2>Output</h2><div class="content">有且仅有一行:一个数,表示答案除以999911659的余数。 </div><h2>Sample Input</h2> <div class="content"><span class="sampledata">4 2<br> </span></div><h2>Sample Output</h2> <div class="content"><span class="sampledata">2048<br> </span></div><h2>HINT</h2> <div class="content"><p>10%的数据中,1 <= N <= 50;<br> 20%的数据中,1 <= N <= 1000;<br> 40%的数据中,1 <= N <= 100000;<br> 100%的数据中,1 <= G <= 1000000000,1 <= N <= 1000000000。<br> </p></div><h2>Source</h2> <div class="content"><p><a href="problemset.php?search=Sdoi2010 Contest2">Sdoi2010 Contest2</a></p></div><center>[<a href="submitpage.php?id=1951">Submit</a>][<a href="problemstatus.php?id=1951">Status</a>][<a href="bbs.php?id=1951">Discuss</a>]</center><br> <a href="./"><span class="red">HOME</span></a> <a href="javascript:history.go(-1)"><span class="red">Back</span></a> </body>javascript
求G^M mod P,M=∑ i|N C(N,i),P=999911659。php
G^M mod P = G^(M mod (P-1) ) ( G != P)。html
因此只要得出 M mod (P-1) 便可用快速幂求出答案。java
N的约数能够在√n的时间内求出,因此问题转化为求C(N,i) mod (P-1)。c++
发现p-1不是一个质数,P-1=234679*35617,因此只能求出C(N,i) mod 每一个因数的值。git
获得4个取模方程,最后用合并模线性方程组。dom
#include<bits/stdc++.h> #define rg register #define il inline #define co const template<class T>il T read(){ rg T data=0,w=1; rg char ch=getchar(); while(!isdigit(ch)){ if(ch=='-') w=-1; ch=getchar(); } while(isdigit(ch)) data=data*10+ch-'0',ch=getchar(); return data*w; } template<class T>il T read(rg T&x){ return x=read<T>(); } typedef long long ll; co int P=999911659; int G,N,M[4]; int fac[4][40005]; int t[4]={2,3,4679,35617}; int qpow(ll a,int b,int p){ int ans=1; for(int i=b;i;i>>=1,a=(a*a)%p) if(i&1) ans=(ans*a)%p; return ans; } int C(int n,int m,int x){ if(n<m) return 0; return fac[x][n]*qpow(fac[x][n-m]*fac[x][m],t[x]-2,t[x])%t[x]; } int lucas(int n,int m,int x){ if(m==0) return 1; return C(n%t[x],m%t[x],x)*lucas(n/t[x],m/t[x],x)%t[x]; } void exgcd(int a,int b,int&x,int&y){ if(b==0) {x=1,y=0;return;} exgcd(b,a%b,x,y); int t=x;x=y,y=t-a/b*y; } int solve(){ int a1,b1,a2,b2,a,b,c,x,y; a1=t[0],b1=M[0]; for(int i=1;i<4;++i){ a2=t[i],b2=M[i]; a=a1,b=a2,c=b2-b1; exgcd(a,b,x,y); x=((c*x)%b+b)%b; b1=b1+a1*x; a1=a1*b; } return b1; } int main() { // freopen(".in","r",stdin),freopen(".out","w",stdout); for(int i=0;i<4;++i){ fac[i][0]=1; for(int j=1;j<=t[i];++j) fac[i][j]=(fac[i][j-1]*j)%t[i]; } read(N),read(G); if(G==P){puts("0");return 0;} G%=P; for(int i=1;i*i<=N;++i) if(N%i==0){ int tmp=N/i; for(int j=0;j<4;++j){ if(tmp!=i) M[j]=(M[j]+lucas(N,i,j))%t[j]; M[j]=(M[j]+lucas(N,tmp,j))%t[j]; } } printf("%d\n",qpow(G,solve(),P)); return 0; }