洛谷P1445 [Violet] 櫻花 (數學)

洛谷P1445 [Violet] 櫻花

題目背景

我很憤怒c++

題目描述

求方程 1/X+1/Y=1/(N!) 的正整數解的組數,其中N≤10^6。spa

解的組數,應模1e9+7。code

輸入輸出格式

輸入格式:get

輸入一個整數Nit

輸出格式:io

輸出答案class

輸入輸出樣例

輸入樣例#1:im

1439統計

輸出樣例#1:di

102426508

Solution

極其噁心的一道題...

看到這種題確定是須要化簡式子的,由於出題人不會好到給你一個好作的式子

\[\frac{1}{x}+\frac{1}{y}=\frac{1}{n!}\]
\[\frac{x+y}{xy}=\frac{1}{n!}\]
\[xy=(n!)\times (x+y)\]
一個騷操做,兩邊同時加上\((n!)^2\),爲何,由於方便因式分解...
\[(n!)^2-(n!)\times (x+y)+xy=(n!)^2\]
而後因式分解
\[(n!-x)\times (n!-y)=(n!)^2\]
\(a=(n!-x),b=(n!-y)\),由於\((n!)^2\)是肯定的,因此肯定了\(a\),就能夠肯定\(b\),也就能夠肯定\(x,y\)

那麼a的方案數是多少?由於\(a\)\((n!)^2\)的因子,因此\(a\)的取值的方案數就是\((n!)^2\)的因子的方案數

而後根據惟一分解定理
\[n!=p_1^{c_1}\times p_2^{c_2}\times ...\times p_m^{c_m}\]
\[(n!)^2=p_1^{2\times c_1}\times p_2^{2\times c_2}\times ...\times p_m^{2\times c_m}\]
因爲每一個質因子\(p_i\)都有\(2\times c_i+1\)種取值,因此
\[ans=(2\times c_1+1)\times (2\times c_2 +1)\times ...\times(2\times c_m+1)\]
那麼最後問題就轉化成了對\(n!\)進行分解質因數,並求質因數的個數

暴力對\(1-n\)每一個數分解質因數,再合併複雜度太高,爲\(O(n\sqrt n)\)

因爲\(n!\)的每一個質因子都不超過n,因此咱們能夠預處理\(1-n\)內全部質數p,再考慮\(n!\)內一共有多少個質因子p

咱們能夠對於在線性篩質數的過程當中同時處理一下n之內每一個數的最小質因子\(p\),而後統計這個數的貢獻,在\(1-n\)中至少包含一個質因子\(p\)的有\(\lfloor\frac{n}{p}\rfloor\),至少包含兩個質因子p的有\(\lfloor\frac{n}{p^2}\rfloor\)...
那麼\(n!\)中質因子\(p\)的個數就是
\[\lfloor\frac{n}{p}\rfloor+\lfloor\frac{n}{p^2}\rfloor+...+\lfloor\frac{n}{p^{log_{p}{n}}}\rfloor\]

對於每一個質因子,咱們只須要\(log\ n\)的時間來求解,因此總複雜度是\(O(n\ log\ n)\)

Code

#include<bits/stdc++.h>
#define rg register
#define il inline
#define Min(a,b) ((a)<(b)?(a):(b))
#define Max(a,b) ((a)>(b)?(a):(b))
#define lol long long
#define in(i) (i=read())
using namespace std;

const lol N=1e6+10,mod=1e9+7;

lol read() {
    lol ans=0,f=1; char i=getchar();
    while(i<'0' || i>'9') {if(i=='-') f=-1; i=getchar();}
    while(i>='0' && i<='9') ans=(ans<<1)+(ans<<3)+i-'0',i=getchar();
    return ans*=f;
}

lol n,cnt,ans=1;
lol g[N],prime[N],c[N];

void init() {
    memset(g,0,sizeof(g));
    for(int i=2;i<=n;i++) {
        if(!g[i]) g[i]=i,prime[++cnt]=i;
        for(int j=1;j<=cnt && i*prime[j]<=n;j++) {
            g[i*prime[j]]=prime[j];
            if(i%prime[j]==0) break;
        }
    }
}

int main()
{ 
    in(n); init();
    for(int i=1;i<=n;i++)
        for(int j=i;j!=1;j/=g[j]) c[g[j]]++;
    for(int i=1;i<=n;i++) ans=ans*(c[i]*2+1)%mod;
    cout<<ans<<endl;
}
相關文章
相關標籤/搜索