bzoj 1951: [Sdoi2010]古代豬文


Description

“在那山的那邊海的那邊有一群小肥豬。他們活潑又聰明,他們調皮又靈敏。他們自由自在生活在那綠色的大草坪,他們善良勇敢相互都關心……” ——選自豬王國民歌 很久很久以前,在山的那邊海的那邊的某片風水寶地曾經存在過一個豬王國。豬王國地理位置偏僻,實施的是適應當時社會的自給自足的庄園經濟,很少與外界聯系,商貿活動就更少了。因此也很少有其他動物知道這樣一個王國。 豬王國雖然不大,但是土地肥沃,屋舍儼然。如果一定要拿什么與之相比的話,那就只能是東晉陶淵明筆下的大家想象中的桃花源了。豬王勤政愛民,豬民安居樂業,鄰里和睦相處,國家秩序井然,經濟欣欣向榮,社會和諧穩定。和諧的社會帶給豬民們對工作火紅的熱情和對未來的粉色的憧憬。 小豬iPig是豬王國的一個很普通的公民。小豬今年10歲了,在大肥豬學校上小學三年級。和大多數豬一樣,他不是很聰明,因此經常遇到很多或者稀奇古怪或者旁人看來輕而易舉的事情令他大傷腦筋。小豬后來參加了全豬信息學奧林匹克競賽(Pig Olympiad in Informatics, POI),取得了不錯的名次,最終保送進入了豬王國大學(Pig Kingdom University, PKU)深造。 現在的小豬已經能用計算機解決簡單的問題了,比如能用P++語言編寫程序計算出A + B的值。這個“成就”已經成為了他津津樂道的話題。當然,不明真相的同學們也開始對他刮目相看啦~ 小豬的故事就將從此展開,伴隨大家兩天時間,希望大家能夠喜歡小豬。 題目描述 豬王國的文明源遠流長,博大精深。 iPig在大肥豬學校圖書館中查閱資料,得知遠古時期豬文文字總個數為N。當然,一種語言如果字數很多,字典也相應會很大。當時的豬王國國王考慮到如果修一本字典,規模有可能遠遠超過康熙字典,花費的豬力、物力將難以估量。故考慮再三沒有進行這一項勞豬傷財之舉。當然,豬王國的文字后來隨着歷史變遷逐漸進行了簡化,去掉了一些不常用的字。 iPig打算研究古時某個朝代的豬文文字。根據相關文獻記載,那個朝代流傳的豬文文字恰好為遠古時期的k分之一,其中k是N的一個正約數(可以是1和N)。不過具體是哪k分之一,以及k是多少,由於歷史過於久遠,已經無從考證了。 iPig覺得只要符合文獻,每一種能整除N的k都是有可能的。他打算考慮到所有可能的k。顯然當k等於某個定值時,該朝的豬文文字個數為N / k。然而從N個文字中保留下N / k個的情況也是相當多的。iPig預計,如果所有可能的k的所有情況數加起來為P的話,那么他研究古代文字的代價將會是G的P次方。 現在他想知道豬王國研究古代文字的代價是多少。由於iPig覺得這個數字可能是天文數字,所以你只需要告訴他答案除以999911659的余數就可以了。

Input

有且僅有一行:兩個數N、G,用一個空格分開。

Output

有且僅有一行:一個數,表示答案除以999911659的余數。

Sample Input

4 2

Sample Output

2048

HINT

10%的數據中,1 <= N <= 50;
20%的數據中,1 <= N <= 1000;
40%的數據中,1 <= N <= 100000;
100%的數據中,1 <= G <= 1000000000,1 <= N <= 1000000000。

Source

Sdoi2010 Contest2

 

傳說中的數論板子大合集,題面是真的好笑;

費馬小定理+CRT+lucas+快速冪+逆元+組合數,大概也就這么點吧;

題目要求mod p;

考慮冪很大我們用歐拉降冪:
a^b mod p =a^(b%phi(p)) mod p;

使用的條件是a,p互質且p為質數,這個是用費馬小定理搞的;

當a,p互質且p為質數,a^p mod p=a,所以a^(p-1) mod p=1;

所以a^b mod p= a^(b mod (p-1)) mod p;

用歐拉降冪的話phi(p)=p-1,所以是一樣的;

然后問題的關鍵在於求:

n有1e9,所以要用lucas求大組合數:

lucas定理:

然后模數不是質數,那么我們考慮常用的方法對每個質因子求一遍然后最后用CRT合並;

因為只有一次詢問,那么我們用sqrt(n)的復雜度枚舉n的每個因子,加到四個模線性方程組中,最后用CRT算出來;

記得注意各個部分的模數不同,lucas和算組合數的時候用prime,CRT的時候用p-1,最后快速冪的時候用p;

//MADE BY QT666
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
typedef long long ll;
const int N=100050;
const int Mod=999911659;
int prime[]={2,3,4679,35617};
int n,g;
ll Ans,sum[N];
ll qpow(ll x,ll y,ll mo){
    ll ret=1;
    while(y){
	if(y&1) (ret*=x)%=mo;
	(x*=x)%=mo;y>>=1;
    }
    return ret;
}
ll jc[10][N];
ll C(int n,int m,int x){
    if(n<m) return 0;
    return jc[x][n]*qpow(jc[x][m],prime[x]-2,prime[x])%prime[x]*qpow(jc[x][n-m],prime[x]-2,prime[x])%prime[x];
}
ll lucas(int n,int m,int x){
    if(m==0) return 1;
    return C(n%prime[x],m%prime[x],x)*lucas(n/prime[x],m/prime[x],x)%prime[x];
}
void Crt(){
    for(int i=0;i<4;i++){
	ll M=(Mod-1)/prime[i];
	(Ans+=sum[i]*M%(Mod-1)*qpow(M,prime[i]-2,prime[i])%(Mod-1))%=(Mod-1);
    }
}
void work(int d){
    for(int i=0;i<4;i++) (sum[i]+=lucas(n,d,i))%=prime[i];
}
int main(){
    scanf("%d%d",&n,&g);if(g==999911659) {puts("0");return 0;}
    for(int i=0;i<4;i++){
	jc[i][0]=1;
	for(int j=1;j<=50000;j++) jc[i][j]=(jc[i][j-1]*j)%prime[i];
    }
    g%=Mod;
    for(int i=1;i*i<=n;i++){
	if(n%i==0){
	    if(i*i==n) work(i);
	    else work(i),work(n/i);
	}
    }
    Crt();
    printf("%lld\n",qpow(g,Ans,Mod));
    return 0;
}

注意!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系我们删除。



 
粤ICP备14056181号  © 2014-2020 ITdaan.com