本文將同步釋出於:
題目
題意簡述
給定 \(y\),求 \(\varphi(x)=y\) 中 \(x\) 的個數和最大值。
\(1\leq y\leq 10^{12}\)。
題解
尤拉函式
解決這個問題,就必然要知道尤拉函式的計算式是什麼。
顯然,尤拉函式的計算式子為:
\[\varphi(x)=\prod_{p_i}(p_i-1)p_i^{c_i-1}
\]
\]
我們不難想到,若 \((p_i-1)\mid y\),那麼 \(x\) 可能含有 \(p_i\) 這個質因數,我們直接搜尋即可。
複雜度證明
冷靜分析,我們不難發現,最劣情況下,一個數 \(y\) 滿足 \(x\) 含有 \(p_i\),則 \((p_i-1)p_i\mid y\),因此本質不同的質因子個數最多有 \(11\) 個,我們參考反素數的貪心分析,不難寫出搜尋程式找到最劣情況,發現搜尋狀態數不多(數量級在 \(10^6\))。
時間複雜度得到了保證。
拓展閱讀
個數:A014197。
最大值:A057635。
參考程式
#include<bits/stdc++.h>
using namespace std;
#define reg register
typedef long long ll;
bool st;
inline ll max(reg ll a,reg ll b){
return a>b?a:b;
}
const int S=1e6;
bool vis[S+1];
int tot,prime[S+1];
inline void Init(reg int n){
for(reg int i=2;i<=n;++i){
if(!vis[i])
prime[++tot]=i;
for(reg int j=1;j<=tot&&i*prime[j]<=n;++j){
vis[i*prime[j]]=true;
if(!(i%prime[j]))
break;
}
}
return;
}
inline bool isPrime(reg ll x){
if(x<=S)
return !vis[x];
else{
for(reg int i=1;i<=tot&&1ll*prime[i]*prime[i]<=x;++i)
if(!(x%prime[i]))
return false;
return true;
}
}
int cnt;
ll Max;
vector<ll> V;
inline void dfs(reg ll y,reg int p,reg ll pod){
if(y==1){
++cnt;
Max=max(Max,pod);
return;
}
if(y+1>V[p]&&isPrime(y+1))
++cnt,Max=max(Max,pod*(y+1));
for(reg int i=p+1,siz=V.size();i<siz&&1ll*(V[i]-1)*(V[i]-1)<=y;++i)
if(!(y%(V[i]-1))){
reg ll ny=y/(V[i]-1),npod=pod*V[i];
dfs(ny,i,npod);
while(!(ny%V[i]))
ny/=V[i],npod*=V[i],dfs(ny,i,npod);
}
return;
}
bool ed;
int main(void){
Init(S);
int t;
scanf("%d",&t);
while(t--){
ll y;
scanf("%lld",&y);
V.clear();
V.push_back(2);
for(reg int i=2;i<=tot;++i)
if(!(y%(prime[i]-1)))
V.push_back(prime[i]);
cnt=Max=0;
dfs(y,0,1),dfs(y,0,2);
reg ll bas=2;
while(!(y&1))
y>>=1,bas<<=1,dfs(y,0,bas);
printf("%d %lld\n",cnt,Max);
}
fprintf(stderr,"%.3lf s\n",1.0*clock()/CLOCKS_PER_SEC);
fprintf(stderr,"%.3lf MiB\n",(&ed-&st)/1048576.0);
return 0;
}