首頁>Club>
6
回覆列表
  • 1 # 使用者1477422223843

    Legendre定理:

    設n為一個正整數,那麼在n!的標準素因子分解式中,素數p的最高次項為L_{p}(n!),則

    L_{p}(n!)=\sum_{k\geq1} \left [ \frac{n}{p^k} \right ]

    當模數不為素數,且不方便使用CRT進行合併時,可以考慮對組合數分解質因數,由於組合數可以寫為一個階乘除以兩個階乘的形式,可以對這三個階乘分別分解質因數,然後使用指數的減法,得到最後組合數的標準分解。

    證明我就不在這裡細說了,反正這個定理可以讓我們快速求出p的指數。

    下面是例題。

    題目描述:

    求方程x_{1}+x_2+......x_k=n的非負整數解的組數n,k≤100,000,答案對20080814取模輸入:

    僅一行,包含兩個正整數n,k。

    輸出:一個整數,表示方程不同解的個數,這個數可能很大,你只需輸出mod 20080814 的結果。

    樣例輸入:

    1 1

    樣例輸出:

    1

    思路分析:

    利用隔板法,答案為\LARGE C_{n+1}^{k-1}

    由於20080814=2*13*772339(3個均為質因數),故可以用CRT。

    也可以用Legendre定理分解階乘的質因數。

    但是此題的輸入有坑,n,k需要特殊處理,詳見程式碼。

    程式碼實現:

    #include<cstdio>

    #include<iostream>

    #include<cstring>

    using namespace std;

    #define ll long long

    ll n,m,p[200005],w[200005],k,ans=1;

    bool v[200005];

    ll olsf()//尤拉篩法求素數

    {for(ll i=2;i<=n+1;i++) { if(!v[i])

    { k++; p[k]=i; v[i] = 1; }

    for(ll j=1;j<=k&&p[j]*i<=n+1;j++)

    { v[i*p[j]]=1;if(i%p[j]==0)

    break; }

    }

    }

    ll qkpow(ll x,ll y)//快速冪不解釋

    {

    ll ans=1;

    while(y)

    {

    if(y&1)

    ans=(ans*x)%20080814;

    x=(x*x)%20080814;

    y/=2;

    }

    return ans%20080814;

    }

    int main()

    {

    scanf("%lld%lld",&m,&n);

    n=n+m-1;

    m--;

    olsf();

    for(ll i=1;i<=k;i++)//求分子的分解

    for(ll j=p[i];j<=n;j*=p[i])

    w[i]+=n/j;

    for(ll i=1;i<=k;i++)//求分母的分解

    for(ll j=p[i];j<=m;j*=p[i])

    w[i]-=m/j;

    for(ll i=1;i<=k;i++)

    for(ll j=p[i];j<=n-m;j*=p[i])

    w[i]-=(n-m)/j;

    for(ll i=1;i<=k;i++)

    ans=(ans*qkpow(p[i],w[i]))%20080814;

    printf("%lld",ans);

  • 中秋節和大豐收的關聯?
  • 水瘦對水產養殖有什麼影響?