【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 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;
}

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

posted @ 2016-10-09 18:47  DaD3zZ  阅读(509)  评论(0编辑  收藏  举报