zoukankan      html  css  js  c++  java
  • hdu 1965 (莫比乌斯函数 莫比乌斯反演)

    GCD

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


    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
     
    Recommend
    wangye   |   We have carefully selected several similar problems for you:  1689 1690 1693 1691 1698 

    此题算是莫比乌斯反演的经典题。
    虽然上面说了把a和c当作1 ,但我们还是把它当做任意数来做。
    对于求(a,b) (c,d)上对应的最大公约数为k这类题,先用容斥原理分为四种:(1,b)与(1,d);(1,c-1)与(1,b);(1,a-1)与(1,d);
    对于每种情况,假设是(1,n)与(1,m)这两个区间(n<m)。
      那这两个区间gcd(x,y)>=k的有(n/k)*(m/k)个。
      若要求最大公约数为k,那么求得便是(n/k)与(m/k)中互质的数的个数。
      接下来就用莫比乌斯函数求这些互质的数的个数了。
      其中我还加入了分段优化。
         最后一步就是去重了,题目说想 G(x,y)==G(y,x),所以要把(a,b) (c,d)里重叠的部分多余的去掉。
      具体【传送门
     1 #include<cstdio>
     2 #include<iostream>
     3 #include<cstring>
     4 #include<cstdlib>
     5 #define clr(x) memset(x,0,sizeof(x))
     6 #define LL long long
     7 using namespace std;
     8 int prime[100010],inf[100010],mu[100010],sum[100010];
     9 long long solve(int n,int m);
    10 void mobius();
    11 int main()
    12 {
    13     int T;
    14     scanf("%d",&T);
    15     int a,b,c,d,k,minx,maxx;
    16     LL  ans;
    17     mobius();
    18     for(int ii=1;ii<=T;ii++)
    19     {
    20         scanf("%d%d%d%d%d",&a,&b,&c,&d,&k);
    21          if(k == 0)
    22          {
    23              printf("Case %d: 0
    ",ii);
    24              continue;
    25          }
    26         ans=solve(b/k,d/k) - solve((a-1)/k,d/k) - solve(b/k,(c-1)/k) + solve((a-1)/k,(c-1)/k);
    27         if((maxx=max(a,c))<(minx=min(b,d)))
    28         ans=ans-(solve(minx/k,minx/k)-solve((maxx-1)/k,minx/k)*2+solve((maxx-1)/k,(maxx-1)/k))/2;
    29         printf("Case %d: %lld
    ",ii,ans);
    30     }
    31     return 0;
    32 }
    33 void mobius()
    34 {
    35     clr(inf);
    36     clr(prime);
    37     clr(sum);
    38     clr(mu);
    39     mu[1] = 1;
    40     inf[1]=inf[0]=1;
    41     int tot = 0;
    42     for(int i = 2; i <= 100000; i++)
    43     {
    44         if( !inf[i] )
    45         {
    46             prime[tot++] = i;
    47             mu[i] = -1;
    48         }
    49         for(int j = 0; j < tot; j ++)
    50         {
    51             if( i * prime[j] > 100000) break;
    52             inf[i * prime[j]] = true;
    53             if( i % prime[j] == 0)
    54             {
    55                 mu[i * prime[j]] = 0;
    56                 break;
    57             }
    58             else
    59             {
    60                 mu[i * prime[j]] = -mu[i];
    61             }
    62         }
    63     }
    64     for(int i = 1;i <= 100000;i++)
    65         sum[i] = sum[i-1] + mu[i];
    66 }
    67 LL solve(int n,int m)
    68 {
    69     LL ans = 0;
    70     if(n > m)swap(n,m);
    71     for(int i = 1, la = 0; i <= n; i = la+1)
    72     {
    73         la = min(n/(n/i),m/(m/i));
    74         ans += (LL)(sum[la] - sum[i-1])*(n/i)*(m/i);
    75     }
    76     return ans;
    77 }
  • 相关阅读:
    快速读取txt文档
    ASP.NET中缓存非SQLServer数据库数据
    查看linq to sql 生成的sql 语句
    跟树有关的数据结构学习系列之概览
    Linux安装软件包时的“依赖关系树”算法(C#)
    Go调度器介绍和容易忽视的问题
    搞懂Go垃圾回收
    Go“一个包含nil指针的接口不是nil接口”踩坑
    Go slice:切片的“陷阱”和本质
    C#调用ODBC连接SQL Server数据库的存储过程
  • 原文地址:https://www.cnblogs.com/wujiechao/p/5897696.html
Copyright © 2011-2022 走看看