zoukankan      html  css  js  c++  java
  • hdu 1695 容斥原理或莫比乌斯反演

    GCD

    Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
    Total Submission(s): 5310    Accepted Submission(s): 1907


    Problem Description
    Given 5 integers: a, b, c, d, k, you're to find x in a...b, y in c...d that GCD(x, y) = k. GCD(x, y) means the greatest common divisor of x and y. Since the number of choices may be very large, you're only required to output the total number of different number pairs.
    Please notice that, (x=5, y=7) and (x=7, y=5) are considered to be the same.

    Yoiu can assume that a = c = 1 in all test cases.
     
    Input
    The input consists of several test cases. The first line of the input is the number of the cases. There are no more than 3,000 cases.
    Each case contains five integers: a, b, c, d, k, 0 < a <= b <= 100,000, 0 < c <= d <= 100,000, 0 <= k <= 100,000, as described above.
     
    Output
    For each test case, print the number of choices. Use the format in the example.
     
    Sample Input
    2 1 3 1 5 1 1 11014 1 14409 9
     
    Sample Output
    Case 1: 9 Case 2: 736427
    Hint
    For the first sample input, all the 9 pairs of numbers are (1, 1), (1, 2), (1, 3), (1, 4), (1, 5), (2, 3), (2, 5), (3, 4), (3, 5).
     
    Source
     
    题目大意:求在1<=x<=b,1<=y<=d上gcd(x,y)=k的(x,y)对数
      1 /************容斥原理*************/
      2 #include <iostream>
      3 #include <cstdio>
      4 #include <cmath>
      5 #include <algorithm>
      6 using namespace std;
      7 
      8 typedef __int64 LL;
      9 const int maxn=1e5+5;
     10 int phi[maxn],prime[maxn],factor[50],num;
     11 bool flag[maxn];
     12 void swap(int &a,int &b){ int t=a;a=b;b=t;}
     13 
     14 void init()//欧拉筛选
     15 {
     16     memset(flag,true,sizeof(flag));
     17     phi[1]=1;
     18     for(int i=2;i<maxn;i++)
     19     {
     20         if(flag[i])
     21         {
     22             prime[num++]=i;
     23             phi[i]=i-1;
     24         }
     25         for(int j=0;j<num&&i*prime[j]<maxn;j++)
     26         {
     27             flag[i*prime[j]]=false;
     28             if(i%prime[j]==0)
     29             {
     30                 phi[i*prime[j]]=phi[i]*prime[j];
     31                 break;
     32             }
     33             else phi[i*prime[j]]=phi[i]*(prime[j]-1);
     34         }
     35     }
     36 }
     37 
     38 void getfactor(int n,int &len)//质因数分解
     39 {
     40     int t=sqrt(n*1.0);len=0;
     41     for(int i=0;i<num&&prime[i]<=t;i++)
     42     {
     43         if(n%prime[i]==0)
     44         {
     45             factor[len++]=prime[i];
     46             while(n%prime[i]==0) n/=prime[i];
     47         }
     48     }
     49     if(n>1) factor[len++]=n;
     50 }
     51 
     52 int getans(int a,int b)
     53 {
     54     int n;
     55     int ans=0;
     56     getfactor(b,n);
     57     for(int i=1;i<(1<<n);i++)//容斥原理
     58     {
     59         int cnt=0,temp=1;
     60         for(int j=0;j<n;j++)
     61         {
     62             if(i&(1<<j))
     63             {
     64                 cnt++;temp*=factor[j];
     65             }
     66         }
     67         if(cnt&1) ans+=a/temp;
     68         else ans-=a/temp;
     69     }
     70     return a-ans;
     71 }
     72 
     73 int main()
     74 {
     75     int i,a,b,c,d,k,t,icase=0;
     76     LL ans;num=0;
     77     init();    
     78     scanf("%d",&t);
     79     while(t--)
     80     {
     81         scanf("%d %d %d %d %d",&a,&b,&c,&d,&k);
     82         if(k==0||k>b||k>d)
     83         {
     84             printf("Case %d: 0
    ",++icase);
     85             continue;
     86         }
     87         ans=0;
     88         b/=k;d/=k;
     89         if(b>d) swap(b,d);
     90         for(i=1;i<=b;i++) ans+=phi[i];
     91         for(i=b+1;i<=d;i++) ans+=getans(b,i);
     92         printf("Case %d: %I64d
    ",++icase,ans);
     93     }
     94     return 0;
     95 }
     96 /*************莫比乌斯反演****************/
     97 #include <iostream>
     98 #include <cstdio>
     99 #include <cstring>
    100 using namespace std;
    101 
    102 typedef __int64 LL;
    103 const int maxn=1e5+5;
    104 int prime[maxn],mu[maxn],num;
    105 bool flag[maxn];
    106 
    107 void init()
    108 {
    109     memset(flag,true,sizeof(flag));
    110     mu[1]=1;
    111     for(int i=2;i<maxn;i++)
    112     {
    113         if(flag[i])
    114         {
    115             prime[num++]=i;mu[i]=-1;
    116         }
    117         for(int j=0;j<num&&i*prime[j]<maxn;j++)
    118         {
    119             flag[i*prime[j]]=false;
    120             if(i%prime[j]==0)
    121             {
    122                 mu[i*prime[j]]=0;
    123                 break;
    124             }
    125             else mu[i*prime[j]]=-mu[i];
    126         }
    127     }
    128 }
    129 
    130 int main()
    131 {
    132     num=0;
    133     init();
    134     int i,a,b,c,d,k,t,icase=0;
    135     scanf("%d",&t);
    136     while(t--)
    137     {
    138         scanf("%d %d %d %d %d",&a,&b,&c,&d,&k);
    139         if(k==0||k>b||k>d)
    140         {
    141             printf("Case %d: 0
    ",++icase);
    142             continue;
    143         }
    144         b=b/k;d=d/k;
    145         if(b>d) swap(b,d);
    146         LL ans=0,ans1=0;
    147         for(i=1;i<=b;i++)
    148             ans+=(LL)mu[i]*(b/i)*(d/i);
    149         for(i=1;i<=b;i++)
    150             ans1+=(LL)mu[i]*(b/i)*(b/i);
    151         ans-=ans1/2;
    152         printf("Case %d: %I64d
    ",++icase,ans);
    153     }
    154     return 0;
    155 }
  • 相关阅读:
    奇怪的人
    假象世界
    心态记录
    民用自组织网络公司概要
    禁止VMware虚拟机与Host的时间同步
    20万左右SUV介绍
    手机GPS为什么能在室内定位?
    取余与位运算
    shell 基础进阶 *金字塔
    shell 、awk两种方法编写9*9法表
  • 原文地址:https://www.cnblogs.com/xiong-/p/3849516.html
Copyright © 2011-2022 走看看