zoukankan      html  css  js  c++  java
  • hdu 1695GCD<容斥>

    链接:http://acm.hdu.edu.cn/showproblem.php?pid=1695

    题意: 在1~a, 1~b中挑出(x,y)满足gcd(x,y) = k , 求(x,y) 的对数 , a,b<=10^5

    思路: gcd(x, y) == k 说明x,y都能被k整除. 问题就可以转化为了求1~a/k 和 1~b/k间互质对数的问题;

    我们让b>=a; 然后在[1....b/k]进行枚举,对于每一个i,我们只要在1...min(i-1,a)中找到与i互质数,记录个数,然后累加就得到结果了;

    当i<=a/k时,我们可以直接用欧拉函数计算出与i互质的个数;

    当i>a/k时,先将i质因数分解,求得[1,2,...,b/k] 里所有能被x的质因数整除的数的个数,即不互质的数的个数,然后用b/k减去即可;

     而 我们枚举i的质因数利用容斥原理, 容斥原理的具体如下:

      区间中与i不互质的个数 = (区间中i的每个质因数的倍数个数)-(区间中i的每两个质因数乘积的倍数)+(区间中i的每3个质因数的成绩的倍数个数)-(区间中i的每4个质因数的乘积)+...

    View Code
     1 #include<iostream>
     2 #include <cstdio>
     3 using namespace std;
     4 const int Max=100005;
     5 __int64 elur[Max];//存放每个数的欧拉函数值
     6 int num[Max];//存放数的素因子个数
     7 int p[Max][20];//存放数的素因子
     8 void init()//筛选法得到数的素因子及每个数的欧拉函数值
     9 {
    10     elur[1]=1;
    11     for(int i=2;i<Max;i++)
    12     {
    13         if(!elur[i])
    14         {
    15             for(int j=i;j<Max;j+=i)
    16             {
    17                 if(!elur[j])
    18                     elur[j]=j;
    19                 elur[j]=elur[j]*(i-1)/i;
    20                 p[j][num[j]++]=i;
    21             }
    22         }
    23         elur[i]+=elur[i-1]; //进行累加(法里数列长度)
    24     }
    25 }
    26 int dfs(int idx,int b,int now)//求不大于b的数中,与now不互质的数的个数;
    27 {                                //dfs()写的容斥原理
    28     int ans=0;
    29     for(int i=idx;i<num[now];i++)//容斥原理来求A1并A2并A3.....并Ak的元素的数的个数.
    30         ans += b/p[now][i]-dfs(i+1,b/p[now][i],now);
    31     return ans;
    32 }
    33 
    34 int main()
    35 {
    36     int t,a,b,c,d,k;
    37     init();
    38     scanf("%d",&t);
    39     for(int ca=1;ca<=t;ca++)
    40     {
    41         scanf("%d%d%d%d%d",&a,&b,&c,&d,&k);
    42         printf("Case %d: ",ca);
    43         if(k==0)
    44         {
    45             printf("0\n");
    46             continue;
    47         }
    48         if(b>d)
    49             swap(b,d);
    50         b/=k;  d/=k;
    51         __int64 ans=elur[b];
    52         for(int i=b+1;i<=d;i++)
    53             ans+=b-dfs(0,b,i);//求不大于b的数中,与i不互质的数的个数
    54         printf("%I64d\n",ans);
    55     }
    56     return 0;
    57 }
  • 相关阅读:
    中国移动全球通寻宝第四期攻略
    推荐一个奥运门票交流的网站!
    国务院发出通知明确2008年部分节假日放假安排
    [转]开发人员如何谈加薪,抛砖引玉,欢迎大家各抒己见。
    中级.NET开发人员应该知道些什么?
    linux系统管理 系统安全及应用
    Linux10 进程 定时任务 僵尸进程
    shell脚本练习
    虚拟机和liunx系统的装机
    Linux三剑客awk的应用对比案例详解
  • 原文地址:https://www.cnblogs.com/jian1573/p/2857003.html
Copyright © 2011-2022 走看看