首页 > 代码库 > 【BZOJ-3643】Phi的反函数 数论 + 搜索

【BZOJ-3643】Phi的反函数 数论 + 搜索

3643: Phi的反函数

Time Limit: 10 Sec  Memory Limit: 64 MB
Submit: 141  Solved: 96
[Submit][Status][Discuss]

Description

技术分享

Input

Output

Sample Input

4

Sample Output

5

HINT

Source

By Zky

Solution

首先答案和N一定是同阶的,所以,可以很暴力的线筛扫一遍求解。

然后根据欧拉函数的式子,我们实际上是可以爆搜的。

爆搜他的质因子然后去凑答案,加最优性剪枝就可以跑过。

最关键的是依据欧拉函数的定义式找到规律!

Code

#include<iostream>#include<cstdio>#include<algorithm>#include<cmath>#include<cstring>using namespace std;#define LL long longinline 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 5100000int 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;}

仔细思考一下应该是可以想到的。

【BZOJ-3643】Phi的反函数 数论 + 搜索