zoukankan      html  css  js  c++  java
  • GCD(洛谷 2568)

    题目描述

    给定整数N,求1<=x,y<=N且Gcd(x,y)为素数的数对(x,y)有多少对.

    输入格式

    一个整数N

    输出格式

    答案

    输入输出样例

    输入 #1

    4

    输出 #1

    4

    说明/提示

    对于样例(2,2),(2,4),(3,3),(4,2)

    1<=N<=10^7



     由题意得gcd(x,y)=p(这里我们假设p为一个已知的质数),并且下面的过程都在这个条件下进行,我们不妨设x<=y<=n

    x=a*py=b*p,则有gcd(a,b)=1,且1<=a,b<=n/p。同样不妨设a<=b(☚什么情况下会等于后面有讲到)。

    那么满足gcd(x,y)=p的数对(x,y)个数其实就是满足gcd(a,b)=1的数对个数(a,b)。(下面用num(x,y)来表示满足gcd(x,y)=p的数对(x,y)个数,num(a,b)同理)

    对于b来说,b的取值范围是1~n/p,而a的取值可以是φ(b)中的任意一个,所以num(x,y)=num(a,b)=∑φ(b)(b∈[1,n/p]),简单来说,就是1~n/p中所有数的欧拉函数值的和


     好,代码已经成功一大半了,但是现在我们并没有p的准确值,p可能是1~n中的任意一个质数。所以我们可以在预处理中先把1~n中的质数(p1、p2……)全部找出来,最后一一枚举这些质数,每枚举一个p,就处理 当gcd(x,y)等于此时的p 的时候的num(x,y),加到最后输出的结果ans中

    代码实现首先,我们用线性筛法求出1~n中每个数的欧拉函数值,用一个数组sum(注意要开long long)来存欧拉函数值的前缀和,方便后面查找值。

    其实可以这样理解,sum[i]存的就是1~i中所有数的欧拉函数值的和,也就是上面讲到的num(x,y)

    那么最后枚举1~n中的质数,每一次循环都得到了一个n/p值,即b的上界,那么此时的sum[n/p]*2-1就是满足gcd(x,y)=p的(x,y)的对数。

    解释一下:由样例可得,(2,4)和(4,2)是不同的两种答案,所以x,y可以交换位置得到一个新的答案,所以sum[n/p]要*2,;但是当a=b=1,即x=y=p时,只有一种答案,所以sum[n/p]*2需要再-1,将重复的删去。

     1 #include<bits/stdc++.h>
     2 #define ll long long
     3 using namespace std;
     4 const int N=10000005;
     5 int n;
     6 ll sum[N],vis[N],p[N],phi[N];
     7 int main()
     8 {
     9     scanf("%d",&n);
    10     memset(vis,1,sizeof(vis));
    11     vis[0]=vis[1]=false;
    12     phi[1]=1;
    13     for(int i=2;i<=n;i++)
    14     {
    15         if(vis[i])p[++p[0]]=i,phi[i]=i-1;//记得找出质数
    16         for(int j=1;j<=p[0]&&p[j]*i<=n;j++)
    17         {
    18             vis[p[j]*i]=false;
    19             if(i%p[j])phi[i*p[j]]=phi[p[j]]*phi[i];
    20             else 
    21             {
    22                 phi[i*p[j]]=p[j]*phi[i];
    23                 break;
    24             }
    25         }//线性筛法
    26     }
    27     for(int i=1;i<=n;i++)sum[i]=sum[i-1]+phi[i];//前缀和
    28     ll ans=0;
    29     for(int i=1;i<=p[0]&&p[i]<=n;i++)//枚举1~n中的所有质数
    30         ans+=(sum[n/p[i]]<<1)-1;//sum[n/p]*2-1
    31     printf("%lld",ans);
    32     return 0;
    33 }
    View Code

    写这篇题解的时候思维比较混乱,我都不知道该如何组织语言了,花了超长时间的!希望能让你理解吧OvO

    如果可以的话,给个“推荐”资瓷一下吧(*^▽^*)

    //参考:zhou_yk 的博客

  • 相关阅读:
    CodeForces 219D Choosing Capital for Treeland (树形DP)
    POJ 3162 Walking Race (树的直径,单调队列)
    POJ 2152 Fire (树形DP,经典)
    POJ 1741 Tree (树的分治,树的重心)
    POJ 1655 Balancing Act (树的重心,常规)
    HDU 2196 Computer (树形DP)
    HDU 1520 Anniversary party (树形DP,入门)
    寒门子弟
    JQuery选择器(转)
    (四)Web应用开发---系统架构图
  • 原文地址:https://www.cnblogs.com/ljy-endl/p/11409675.html
Copyright © 2011-2022 走看看