| 欧拉函数 |
| Time Limit: 3000ms, Special Time Limit:6000ms, Memory Limit:65536KB |
| Total submit users: 73, Accepted users: 59 |
| Problem 11550 : No special judgement |
| Problem description |
| 一个数x的欧拉函数Φ(x)定义为所有小于x的正整数中与x互质的数的数目,如小于5且和5互质的数有1、2、3、4,一共4个,故Φ(5)=4。
对于任意正整数x,我们定义两种操作: |
| Input |
| 每行输入一个整数a(0<a<=100000)。 |
| Output |
| 输出需要的步数,如果无法得到,输出-1; |
| Sample Input |
2 3 |
| Sample Output |
1 2 |
| Problem Source |
| HUNNU Contest |
如果你不知道求欧拉函数的话那么这题还是不要看了,就像我一样~~
打欧拉表的是网上找的,我自己写的只有下面的dp
#include <cstdio>
#include <cstring>
#include <iostream>
#include <malloc.h>
#define LL long long
using namespace std;
const LL N = 100001;
LL n;
LL *phi,i,j;
char *prime;
LL flog;
LL visit[N];
LL dp[N],num[N];
int main()
{
prime=(char*)malloc((N+1)*sizeof(char));
prime[0]=prime[1]=0;
for(i=2; i<N; i++)
prime[i]=1;
for(i=2; i*i<N; i++)
{
if(prime[i])
{
for(j=i*i; j<=N; j+=i)
{
prime[j]=0;
}
}
} //这段求出了N内的所有素数
phi=(LL*)malloc((N+1)*sizeof(LL));
for(i=1; i<N; i++)
{
dp[i]=N;//dp初始化
phi[i]=i;
}
for(i=2; i<N; i++)
{
if(prime[i])
{
for(j=i; j<N; j+=i)
{
phi[j]=phi[j]/i*(i-1); //此处注意先/i再*(i-1),否则范围较大时会溢出
}
}
}//以上都是打表部分,表示没细心去看,导致连注释都懒得改了,原创大哥看到了别喷我~
dp[1]=0;
//dp的递推思路就是用小点推出大点,因为上面两个公式是递增的,所以从小到大来遍历的话,每次遍历到的点都是已经求出了最优方案的
for(i=1;i<N;i++)
{
if(i+phi[i]<N&&dp[i+phi[i]]>dp[i]+1)//用公式1如果没有过界,同时当前方案用的步数更少,那么替换
dp[i+phi[i]]=dp[i]+1;
if(i*phi[i]<N&&dp[i*phi[i]]>dp[i]+1)//用公式2如果没有过界,同时当前方案用的步数更少,那么替换
dp[i*phi[i]]=dp[i]+1;
}
while(scanf("%lld",&n)!=-1)
{
if(dp[n]<N)//因为dp初始化就是N,所以这一步不能少。
printf("%lld\n",dp[n]);
else
printf("-1\n");
}
return 0;
}
原文:http://blog.csdn.net/jingdianitnan/article/details/46418461