[Sdoi2010]古代豬文

<body> <center> <h1>1951: [Sdoi2010]古代豬文</h1> <span class="green">Time Limit: </span>1 Sec&nbsp;&nbsp; <span class="green">Memory Limit: </span>64 MB<br> <span class="green">Submit: </span>3897&nbsp;&nbsp;<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 &lt;= N &lt;= 50;<br> 20%的數據中,1 &lt;= N &lt;= 1000;<br> 40%的數據中,1 &lt;= N &lt;= 100000;<br> 100%的數據中,1 &lt;= G &lt;= 1000000000,1 &lt;= N &lt;= 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

hzwer的題解

求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;
}
相關文章
相關標籤/搜索