HDU1787 GCD again 欧拉公式 的运用


函数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一定为质数.?
arkdown写东西,感觉很新奇.

题意的要求是给出一个数N求小于N与N不互质的数,而N相当打,显然用暴力一个一个的求显然是行不通的,那么我们应该怎么办呢??
既然求与他不互质的很烦,我们我们尝试去求与他互质的数目,再拿N减去不就好了么??

#include<stdio.h>
using namespace std;
__int64 eural(__int64 n)
{
    __int64 res = n;
    for(int i = 2;i*i <= n;i++)
    {
        if(n % i == 0)
        res = res/i*(i-1);
        while(n % i == 0)
        n /= i;
    }
    if(n > 1)
    res = res/n*(n - 1);
    return res;
}
int main()
{
    __int64 n;
    while(scanf("%I64d",&n),n)
        printf("%I64d\n",n - 1 - eural(n));
        return 0;
} 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值