zoukankan      html  css  js  c++  java
  • [bzoj 2818]GCD

    Gcd

    Time Limit: 10 Sec  Memory Limit: 256 MB

    Description

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

    Input

    一个整数N

    Output

    如题

    Sample Input

    4

    Sample Output

    4

    HINT

    hint

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


    1<=N<=10^7

    题解:
    根据题意,我们要求求1<=x,y<=N且Gcd(x,y)为素数的数对(x,y)有多少对。

    显然我们不可能将1到N的所有数对都枚举一遍,现在考虑枚举所有质数。

    因为gcd(a,b)==p(p为质数),所以gcd(a/p,b/p)==1;

    那么我们只要枚举所有小于N的质数,然后找⌊a/p⌋和⌊b/p⌋互质的对数。

    显然只要先预处理出欧拉函数,然后用一层循环枚举1~⌊a/p⌋统计一下和就可以了。

    注意一下几点:

    1.每次统计都要乘上2,因为反过来也算一个数对。比如样例中2,4和4,2是不同的数对。

    2.每次统计完之后ans-- 因为每次统计都乘2必然会有一个包含两个相同数的数对被多计算一次,比如样例中2,2和3,3都被计算了两次,所以要被减掉。

    3.至于怎么筛质数,欧拉函数,以及高端大气上档次的莫比乌斯函数,实际上可以同时做到。

    void find_prime(int listsize)
    {
        int i,j;
        memset(isprime,1,sizeof(isprime));
        isprime[1]=false;
        phi[1]=1;
        mu[1]=1;
        for(i=2;i<=listsize;i++)
        {
            if(isprime[i])
            {
                prime[++primesize]=i;
                phi[i]=i-1;
                mu[i]=-1;
            }
            for(j=1;j<=primesize&&i*prime[j]<=listsize;j++)
            {
                isprime[i*prime[j]]=false;
                if(i%prime[j]==0)
                {
                    phi[i*prime[j]]=phi[i]*prime[j];
                    mu[i*prime[j]]=0;
                    break;
                }
                else 
                {
                    phi[i*prime[j]]=phi[i]*(prime[j]-1);
                    mu[i*prime[j]]=-mu[i];
                }
            }
        }
        return;
    }

    然后附上AC代码:

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<cstdlib>
    #include<algorithm>
    using namespace std;
    typedef long long lol;
    bool isprime[10000001];
    int prime[5000001],primesize,phi[10000001],n;
    lol ans;
    void find_prime(int listsize)
    {
        int i,j;
        memset(isprime,1,sizeof(isprime));
        isprime[1]=false;
        phi[1]=1;
        for(i=2;i<=listsize;i++)
        {
            if(isprime[i])
            {
                prime[++primesize]=i;
                phi[i]=i-1;
            }
            for(j=1;j<=primesize&&i*prime[j]<=listsize;j++)
            {
                isprime[i*prime[j]]=false;
                if(i%prime[j]==0)
                {
                    phi[i*prime[j]]=phi[i]*prime[j];
                    break;
                }
                else 
                {
                    phi[i*prime[j]]=phi[i]*(prime[j]-1);
                }
            }
        }
        return;
    }
    int main()
    {
        int i,j;
        scanf("%d",&n);
        find_prime(n);
        for(i=1;i<=primesize;i++)
        {
            int to=n/prime[i];
            for(j=1;j<=to;j++)
            ans+=phi[j]*2;
            ans--;
        }
        printf("%lld
    ",ans);
        return 0;
    }
  • 相关阅读:
    WINRAR发现溢出漏洞 3.6以下的版本全遭殃!
    Linux桌面即将奢华:KDE 4.1 Beta 1颁发
    AMD Catalyst 8.5 For Linux
    解说MySQL数据库的数据典范和建库战略
    FVWMCrystal:美观且易用的桌面环境
    Linux下建立ISO映像,运用ISO映像,卸载ISO映像
    KDiff3:文件及目次比拟/兼并东西
    Ubuntu 8.04装置nVidia新版显现驱动
    在linux浏览CHM文件
    SCN不差别将会招致ORA00600 2662错误
  • 原文地址:https://www.cnblogs.com/huangdalaofighting/p/7275988.html
Copyright © 2011-2022 走看看