• nyoj 998


    nyoj 998    点击这里打开题目链接

       给你一个数N,使得在1~N之间能够找到x使得x满足gcd( x ,  N  ) >= M,

    求解gcd(x,N)的和


    思路:一开始想到暴力法做,超时 ,后来借鉴学长经验AC:

    大致思路: 用欧拉函数求 ,euler(n) 表示 1到n与n互质的数的个数,  如果n能够被 i 整除 ,

             则euler(n/i)等价于gcd(x,N)==i 的个数  (x是从1到n的所有数字)。


    所以,你会想到一个for循环,因为gcd(x,N)的值为1到n  枚举  gcd为M到n,再来求和? 时间复杂度也会很高,

    所以并不需要全部一一枚举 

            比如gcd(x,N)  N为  10  , 它们的gcd  只有  1,10    2,5

                                        N为15    它们的gcd  有  1,15,   3,5   

           所以它们的gcd  只需要知道1  到 根号n 而另外一个gcd   为  n/i  ;

    for(i=1;i*i<=n;i++)
     {
          if(n%i==0)
          {
              if(i>=m)            sum+=i*euler(n/i);
              if(i*i!=n&&n/i>=m)  sum+=(n/i)*euler(i);  
          }
     }
    注意:  第二个if  i *i!=n  因为在第一个if里面已经加过了 


    下面贴个代码



    #include <stdio.h>
    #include <math.h>
    
    long long euler(long long n)
    {
        long long i,sum=n,temp=n;
        for(i=2;i*i<=temp;i++)
        {
            if(n%i==0)
            {
                sum=sum/i*(i-1);
                while(n%i==0)
                    n/=i;
            }
        }
        if(n>1)
            sum=sum/n*(n-1);
        return sum;
    }
    
    int main()
    {
        long long m,n;
        while((scanf("%lld %lld",&n,&m))!=EOF)
        {
            long long sum=0,i;
            for(i=1;i*i<=n;i++)
            {
                if(n%i==0)
                {
                    if(i>=m)            sum+=i*euler(n/i);
                    if(i*i!=n&&n/i>=m)  sum+=(n/i)*euler(i);
                }
            }
            printf("%lld
    ",sum);
        }
        return 0;
    }
    



  • 相关阅读:
    设计模式
    TCP拥塞控制
    TCP 连接建立和断开,以及状态转换
    python unicode字符串
    python语法笔记(七)
    python语法笔记(六)
    python语法笔记(五)
    python语法笔记(四)
    python语法笔记(三)
    【密码学】公钥与私钥
  • 原文地址:https://www.cnblogs.com/coded-ream/p/7208004.html
Copyright © 2020-2023  润新知