【BZOJ-3643】Phi的反函数 数论 + 搜索
3643: Phi的反函数
Time Limit: 10 Sec Memory Limit: 64 MBSubmit: 141 Solved: 96
[Submit][Status][Discuss]
Description
Input
Output
Sample Input
4
Sample Output
5
HINT
Source
Solution
首先答案和N一定是同阶的,所以,可以很暴力的线筛扫一遍求解。
然后根据欧拉函数的式子,我们实际上是可以爆搜的。
爆搜他的质因子然后去凑答案,加最优性剪枝就可以跑过。
最关键的是依据欧拉函数的定义式找到规律!
Code
#include<iostream> #include<cstdio> #include<algorithm> #include<cmath> #include<cstring> using namespace std; #define LL long long inline int read() { int x=0,f=1; char ch=getchar(); while (ch<'0' || ch>'9') {if (ch=='-') f=-1; ch=getchar();} while (ch>='0' && ch<='9') {x=x*10+ch-'0'; ch=getchar();} return x*f; } #define MAXN 5100000 int X,N; int prime[MAXN],flag[MAXN],cnt; void Getprime() { flag[1]=1; cnt=0; for (int i=2; i<=N; i++) { if (!flag[i]) prime[++cnt]=i; for (int j=1; j<=cnt && prime[j]*i<=N; j++) { flag[i*prime[j]]=1; if (prime[j]%i==0) break; } } } LL ans=(1LL<<30); LL sqr(LL x) {return (LL)x*x;} bool check(int x) { // if (flag[x]) return 0; for (int i=1; sqr(prime[i])<=x && i<=cnt; i++) if (x%prime[i]==0) return 0; return 1; } void DFS(int dep,LL sum,LL x,int last) { if (sum>=ans) return; if (x==1) {ans=sum; return;} if (check(x+1) && sqr(x)>X) ans=min(ans,sum*(x+1)); for (int i=last+1; (prime[i]-1)<=x && sqr(prime[i]-1)<=X; i++) if (!(x%(prime[i]-1))) { LL xx=(LL)x/(prime[i]-1),summ=(LL)sum*prime[i]; DFS(dep+1,summ,xx,i); while (!(xx%prime[i])) xx=(LL)xx/prime[i],summ=(LL)summ*prime[i],DFS(dep+1,summ,xx,i); } } int main() { X=read(); N=int(sqrt(X))+1010; if (X==1) {puts("1"); return 0;} Getprime(); DFS(1,1LL,(LL)X,1); printf("%lld\n",ans==(1LL<<30)? -1:ans); return 0; }
仔细思考一下应该是可以想到的。
——It's a lonely path. Don't make it any lonelier than it has to be.