1. 程式人生 > 實用技巧 >LG P2480 [SDOI2010]古代豬文

LG P2480 [SDOI2010]古代豬文

Description

豬王國的文明源遠流長,博大精深。

iPig 在大肥豬學校圖書館中查閱資料,得知遠古時期豬文文字總個數為 $n$。當然,一種語言如果字數很多,字典也相應會很大。當時的豬王國國王考慮到如果修一本字典,規模有可能遠遠超過康熙字典,花費的豬力、物力將難以估量。故考慮再三沒有進行這一項勞豬傷財之舉。當然,豬王國的文字後來隨著歷史變遷逐漸進行了簡化,去掉了一些不常用的字。

iPig 打算研究古時某個朝代的豬文文字。根據相關文獻記載,那個朝代流傳的豬文文字恰好為遠古時期的$\frac 1k$,其中 $k$是 $n$的一個正約數(可以是 $1$或 $n$)。不過具體是哪 $\frac 1k$,以及 $k$是多少,由於歷史過於久遠,已經無從考證了。

iPig 覺得只要符合文獻,每一種$k|n$都是有可能的。他打算考慮到所有可能的 $k$。顯然當 $k$等於某個定值時,該朝的豬文文字個數為 $\frac nk$。然而從 $n$個文字中保留下 $\frac nk$個的情況也是相當多的。iPig 預計,如果所有可能的 $k$的所有情況數加起來為$p$的話,那麼他研究古代文字的代價將會是 $g^p$

現在他想知道豬王國研究古代文字的代價是多少。由於 iPig 覺得這個數字可能是天文數字,所以你只需要告訴他答案除以 $999911659$的餘數就可以了。

Solution

題目要求$g^{\sum{d|n\ C_n^d}}\ mod\ 999911659$

分類討論

當底數與模數互質時可以用尤拉定理推得

$$g^{\sum{d|n\ C_n^d}}\ mod\ 999911659=g^{\sum{d|n\ C_n^d\ mod\ 999911658}}\ mod\ 999911659$$

模數大得飛起,不能直接Lucas,於是質因數分解模數

$$999911659=2 \times 3 \times 4679 \times 35617$$

所以可以計算$\sum{d|n\ C_n^d}$模這四個數的值,用CRT求解方程組

$$\left\{\begin{matrix}
x \equiv a_1 & \mod 2\\
x \equiv a_2 & \mod 3\\
x \equiv a_3 & \mod 4679\\
x \equiv a_4 & \mod 35617
\end{matrix}\right. $$

解出$x$後快速冪求解

當底數與模數不互質時特判

#include<iostream>
#include<cstdio>
using namespace std;
long long n,g,fac[]={0,2,3,4679,35617},a[10],jc[50005],inv[50005],ans;
const long long mod=999911658;
inline long long read()
{
    long long f=1,w=0;
    char ch=0;
    while(ch<'0'||ch>'9')
    {
        if(ch=='-')
            f=-1;
        ch=getchar();
    }
    while(ch>='0'&&ch<='9')
    {
        w=(w<<1)+(w<<3)+ch-'0';
        ch=getchar();
    }
    return f*w;
}
long long ksm(long long a,long long p,long long m)
{
    long long ret=1;
    while(p)
    {
        if(p&1)
        {
            (ret*=a)%=m;
        }
        (a*=a)%=m;
        p>>=1;
    }
    return ret;
}
void pre(long long p)
{
    jc[0]=1;
    for(long long i=1;i<=p;i++)
    {
        jc[i]=jc[i-1]*i%p;
    }
}
long long C(long long x,long long y,long long p)
{
    if(x<y)
    {
        return 0;
    }
    return jc[x]*ksm(jc[y],p-2,p)%p*ksm(jc[x-y],p-2,p)%p;
}
long long lucas(long long x,long long y,long long p)
{
    if(!x)
    {
        return 1;
    }
    return lucas(x/p,y/p,p)*C(x%p,y%p,p)%p;
}
void CRT()
{
    for(long long i=1;i<=4;i++)
    {
        (ans+=a[i]*(mod/fac[i])%mod*ksm(mod/fac[i],fac[i]-2,fac[i])%mod)%=mod;
    }
}
int main()
{
    n=read();
    g=read();
    if(!(g%(mod+1)))
    {
        puts("0");
        return 0;
    }
    for(long long i=1;i<=4;i++)
    {
        pre(fac[i]);
        for(long long j=1;j*j<=n;j++)
        {
            if(!(n%j))
            {
                (a[i]+=lucas(n,j,fac[i]))%=fac[i];
                if(j*j!=n)
                {
                    (a[i]+=lucas(n,n/j,fac[i]))%=fac[i];
                }
            }
        }
    }
    CRT();
    printf("%lld\n",ksm(g,ans,mod+1)%(mod+1));
    return 0;
}
[SDOI2010]古代豬文