HDU1787 GCD Again

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 0

Sample Output
0 1

Author
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西,.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值