1. 程式人生 > >BZOJ 1951 淺談豬王國古代文字及中國剩餘定理合併半拓展LuCas

BZOJ 1951 淺談豬王國古代文字及中國剩餘定理合併半拓展LuCas

這裡寫圖片描述
世界真的很大
本來只是想找一道水題熱熱手,結果調了好久,聽說大佬都是1A太強了
前幾天做了一道拓展Lucas以為這道題也是但是其實沒有那麼複雜
如果是拓展Lucas那麼mod數一般會給出,像這種直接告訴你的肯定有貓膩,仔細一分析就能發現

看題先:

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的餘數。

題目巨長系列
說白了就是列舉n的所有因數,算一個C(n,k)加起來,在算G的這麼多次方
考慮前面算的組合數多的位置都是在G的指數位置,所以說可以用尤拉定理來優化一下,指數mod一個phi(m)
那麼求組合數時的mod數就是這個phi了
問題在於999911659是一個質數,那他的phi就是999911658,恰恰是一個合數,對合數求組合數,這不是拓展Lucas嗎?
考慮這個999911659,作為題目給出的mod數卻不是1e9+7之類的司空見慣的數,有點怪
999911659-1得到999911658
這個東西質因數一分解,就是 2,3,4679,35617,全是質數,對於每一個質數可以使用Lucas,算出來5個值再用中國剩餘定理合起來就好啦

然而我一開始先是打表沒有打出35617,調了好久才發現
之後又是Lucas的時候mod寫成了999911659而不是mi,orz
兩個小時就這麼過去了

完整程式碼:

#include<stdio.h>
#include<cstring>
using namespace std;
typedef long long dnt ;

const dnt mod=999911659;

dnt n,G;
dnt saber[5][100050],inv[5][100050],m[5]={0,2,3,4679,35617};

void init(dnt m,int typ)
{
    saber[typ][0
]=inv[typ][0]=inv[typ][1]=1; for(int i=1;i<=m;i++) saber[typ][i]=saber[typ][i-1]*i%m; for(int i=2;i<=m;i++) inv[typ][i]=(m-m/i)*inv[typ][m%i]%m; for(int i=1;i<=m;i++) inv[typ][i]=inv[typ][i-1]*inv[typ][i]%m; } void exgcd(dnt a,dnt b,dnt &x,dnt &y) { if(b==0) { x=1,y=0; return ; } dnt x0,y0; exgcd(b,a%b,x0,y0); x=y0,y=x0-a/b*y0; } dnt inverse(dnt a,dnt m) { dnt x,y; exgcd(a,m,x,y); return (x%m+m)%m; } dnt Misaka(dnt a,dnt b,dnt m,int typ) { if(a<b) return 0; if(a<m) return saber[typ][a]*inv[typ][b]%m*inv[typ][a-b]%m; return Misaka(a%m,b%m,m,typ)*Misaka(a/m,b/m,m,typ)%m; } dnt CRT(dnt a,dnt b) { dnt rt=0,Mod=mod-1; for(int i=1;i<=4;i++) { dnt tmp=Misaka(a,b,m[i],i); rt=(rt+(Mod/m[i])*tmp%Mod*inverse(Mod/m[i],m[i])%Mod)%Mod; } return rt%Mod; } dnt cal() { dnt rt=0; for(dnt i=1;i*i<=n;i++) { if(n%i) continue ; rt=(rt+CRT(n,i))%(mod-1); if(i!=n/i) rt=(rt+CRT(n,n/i))%(mod-1); } return rt%(mod-1); } dnt quickmub(dnt a,dnt b) { dnt rt=1; while(b) { if(b&1) rt=rt*a%mod; a=a*a%mod,b>>=1; } return rt; } int main() { for(int i=1;i<=4;i++) init(m[i],i); scanf("%lld%lld",&n,&G); dnt idx=cal(); printf("%lld\n",quickmub(G,idx+mod-1)); return 0; } /* EL PSY CONGROO */

嗯,就是這樣