1. 程式人生 > >P2480 [SDOI2010]古代豬文

P2480 [SDOI2010]古代豬文

漸進 dom 穩定 不常用 地理位置 () 中國 多少 ase

P2480 [SDOI2010]古代豬文

題目背景

“在那山的那邊海的那邊有一群小肥豬。他們活潑又聰明,他們調皮又靈敏。他們自由自在生活在那綠色的大草坪,他們善良勇敢相互都關心……”

——選自豬王國民歌

很久很久以前,在山的那邊海的那邊的某片風水寶地曾經存在過一個豬王國。豬王國地理位置偏僻,實施的是適應當時社會的自給自足的莊園經濟,很少與外界聯系,商貿活動就更少了。因此也很少有其他動物知道這樣一個王國。

豬王國雖然不大,但是土地肥沃,屋舍儼然。如果一定要拿什麽與之相比的話,那就只能是東晉陶淵明筆下的大家想象中的桃花源了。豬王勤政愛民,豬民安居樂業,鄰裏和睦相處,國家秩序井然,經濟欣欣向榮,社會和諧穩定。和諧的社會帶給豬民們對工作火紅的熱情和對未來的粉色的憧憬。

小豬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的余數就可以了。

輸入輸出格式

輸入格式:

輸入文件ancient.in有且僅有一行:兩個數N、G,用一個空格分開。

輸出格式:

輸出文件ancient.out有且僅有一行:一個數,表示答案除以999911659的余數。

輸入輸出樣例

輸入樣例#1:
4 2
輸出樣例#1:
2048

說明

數據規模

10%的數據中,1 <= N <= 50;

20%的數據中,1 <= N <= 1000;

40%的數據中,1 <= N <= 100000;

100%的數據中,1 <= G <= 1000000000,1 <= N <= 1000000000。

————————————————————————————————————————————————————————————————
數論大模板

就是求$G^{\sum\limits_{d|N}{C_N^d}}(\mod999911659)$

G=999911659時上式等於0,否則由歐拉定理得$G^{\sum\limits_{d|N}{C_N^d}}≡G^{\sum\limits_{d|N}{C_N^d\mod999911659}}(\mod999917659)$

$999917659=2*3*4678*35617$,枚舉N的約數d,Lucas定理求組合數$C_{N}^{d}$,分別計算出$\sum\limits_{d|N}C_N^d$對2,3,4679,35617取模的結果,記為a1,a2,a3,a4

中國剩余定理求解線性同余方程組

$x\mod2=a1$

$x\mod3=a2$

$x\mod4769=a3$

$x\mod35617=a4$

最後快速冪求$G^x$

code

#include <algorithm>
#include <cctype>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <queue>
#include <vector>

typedef long long LL;
typedef double db;
const int MAXN = 1000010;
LL N, G;
LL f[MAXN]={1}, a[4] = {2, 3, 4679, 35617}, b[MAXN];

inline LL read() {
    LL num = 0, f = 1; char ch = getchar();
    while (!isdigit(ch)) {if (ch == -) f = -1; ch = getchar();}
    while (isdigit(ch)) {num = num * 10 + ch - 0; ch = getchar();}
    return num * f;
}

LL FastPow(LL a, LL b, LL MO) {
    LL ans = 1, base = a;
    while (b) {
        if (b & 1) ans = ans * base % MO;
        base = base * base % MO;
        b >>= 1;
    } return ans;
}

LL C(LL n, LL m, LL p) {
    if (n < m) return 0;
    return f[n] * FastPow(f[n - m] * f[m], p - 2, p) % p;
}

LL Lucas(LL n, LL m, LL p) {
    if (m == 0) return 1;
    return C(n % p, m % p, p) * Lucas(n / p, m / p, p) % p;
}

LL CRT() {
    LL ans = 0, MO = 999911658;
    for (int i = 0; i < 4; ++ i) {
        LL t = MO / a[i];
        ans = (ans + 1LL*b[i]*t%MO * FastPow(t,a[i]-2,a[i])%MO) % MO;
    } return ans;
}
int main() {
    N = read(); G = read();
    if (G == 999911659) {
        std::cout << "0" << std::endl;
        return 0;
    }
    for (int i = 0; i < 4; ++ i) {
        f[0] = 1;
        for (int j = 1; j <= a[i]; ++ j) 
            f[j] = f[j - 1] * j % a[i];
        for (int j = 1; j * j <= N; ++ j) {
            if (N % j) continue;
            b[i] = (b[i] + Lucas(N, j, a[i])) % a[i];
            if (N / j == j) continue;
            b[i] = (b[i] + Lucas(N, N / j, a[i])) % a[i];
        }
    }
    LL ans = FastPow(G, CRT(), 999911659);
    std::cout << ans << std::endl;
    return 0;
}

P2480 [SDOI2010]古代豬文