HDU-1787 GCD Again
欧拉公式
Problem Description
Do you have spent some time to think and try to solve those unsolved problem after one ACM contest?
No? Oh, you must do this when you want to become a “Big Cattle”.
Now you will find that this problem is so familiar:
The greatest common divisor GCD (a, b) of two positive integers a and b, sometimes written (a, b), is the largest divisor common to a and b. For example, (1, 2) =1, (12, 18) =6. (a, b) can be easily found by the Euclidean algorithm. Now I am considering a little more difficult problem:
Given an integer N, please count the number of the integers M (0<M<N) which satisfies (N,M)>1.
This is a simple version of problem “GCD” which you have done in a contest recently,so I name this problem “GCD Again”.If you cannot solve it still,please take a good think about your method of study.
Good Luck!Input
Input contains multiple test cases. Each test case contains an integers N (1<N<100000000). A test case containing 0 terminates the input and this test case is not to be processed.Output
For each integers N you should output the number of integers M in one line, and with one line of output for each line in input.Sample Input
2 4 0Sample Output
0 1Author
lcy
题意的要求是给出一个数N求小于N与N不互质的数,而N相当打,显然用暴力一个一个的求显然是行不通的,那么我们应该怎么办呢?
既然求与他不互质的很烦,我们我们尝试去求与他互质的数目,再拿N减去不就好了么?
至于如何求互质个数,还好我们不用再去自己思考(大概还是暴力吧–),欧拉(就是发明那个GCD的)已经求出了欧拉公式:φ(x)=x(1-1/p1)(1-1/p2)(1-1/p3)(1-1/p4)…..(1-1/pn)
,φ(x)
为小于x与x互质数的个数,而p1
,p2
则是x的质因子.
* 那么代码如下:
#include <iostream>
using namespace std;
long long Eural(long long N)
{
long long Res=N;//用于保存结果
for(int i=2;i*i<=N;i++)
{
if(N%i==0)
Res=Res/i*(i-1);
while(N%i==0)
N=N/i;
}
if(N>1)
Res=Res/N*(N-1);
return Res;
}
int main()
{
long long N;
while(cin>>N)
{
if(N==0)
break;
long long Res=N-1-Eural(N);//注意要减去1,应为1不满足题目条件
cout<<Res<<endl;
}
return 0;
}
函数Eural就是欧拉公式的模板了,这里还是要有些注意的在在乘以(i-1)/i的时候,我们是先除再乘的,为什么这样做呢?因为这样可以避免中间结果的溢出,
而在for循环里边的条件写的也很有意思,我们并没有直接循环到N而是循环到了
N−−√
,如果是22的话,那么岂不是循环到4就结束了么?别担心,N是动态变化的,而且我们可以保证N循环结束的时候是质数或者为1,因为不存在两个大于
N−−√
的因子,如果有的话,那么他们乘积一定大于N,所以最多存在一个大于
N−−√
的因子,而最后的一个if(),就补上了这个漏洞.
那么读完了代码,你是否还是觉得哪里不对劲?没错,我们没有确认i是否为质数,为什么还是正确的呢?假设存在一个i为非质数,且N%i==0,因为N%i==0,且i非质数,那么gcd(N,i)=a ,a!=1,那么在i==a的时候我们就可以发现这种情况是不存在的,因为N%a一定等于0,而在if语句中我们用while循环出去了N中所有的a,故之后N%i一定不会为0的.故i一定为质数.
第一次使用Markdown写东西,感觉很新奇.