zoukankan      html  css  js  c++  java
  • HDU4135 Coprime 容斥定理

    该题就是给定一个数,求某个区间内有多少数与这个数互质。

    首先我们要明确,对于一个给定的区间,我们如果能够求出这个区间内所有与其不互质的数的个数的话,那么互质数的个数也就求出来。这个叫做反面求解。

    对于任何一个正整数N,都有其唯一的素因子分解形式,我们可以这样想,任何与N不互质的数一定是其某一个质因子的倍数,所以我们通过某一个质因子能够确定一个范围内的有多少个数该质因子的倍数的数。但是这并不是所有不互质数的充分条件,对于另外的质因子同样满足能够确定一系列的数,我们要做的就是融过容斥定理求他们的并集。

    代码如下:

    #include <cstdlib>
    #include <cstring>
    #include <cstdio>
    #include <cmath>
    using namespace std;
    
    typedef long long int Int64;
    
    Int64 a, b, num, rec[6000000], lim, ans;
    
    int idx;
    
    Int64 GCD(Int64 a, Int64 b)
    {
        Int64 t;
        while (b) {
            t = a;
            a = b;
            b = t % b;
        }
        return a;
    }
    
    Int64 LCM(Int64 a, Int64 b)
    {
        return a / GCD(a, b) * b;
    }
    
    void dfs(int p, Int64 co, int sign)
    {
        if (p > idx) {
            return;
        }
        if (p > 0) {
            ans += sign * (b / co - (a-1) /co);
        }
        for (int i = p + 1; i <= idx; ++i) {
            dfs(i, LCM(co, rec[i]), -sign);
        }
    }
    
    int main()
    {
        int T, ca = 0;
        scanf("%d", &T);
        while (T--) {
            idx = 0;
            ans = 0;
            scanf("%I64d %I64d %I64d", &a, &b, &num);
            if (num == 1) {
                printf("Case #%d: %I64d\n", ++ca, b-a+1);
                continue;
            }
            lim = (int)sqrt(double(num));
            if (num % 2 == 0) {
                while (num % 2 == 0) {
                    num >>= 1;
                }
                rec[++idx] = 2;
            }
            for (int i = 3;  i <= lim; ++i) {
                if (num % i == 0) {
                    while (num % i == 0) {
                        num /= i;
                    }
                    rec[++idx] = i;
                }
            }
            
            if (num != 1) {
                rec[++idx] = num;
            }
            
            dfs(0, 1, -1);
            printf("Case #%d: %I64d\n", ++ca, b - a + 1 - ans);
        }
        return 0;
    }
  • 相关阅读:
    VC++MFC对话框程序中给对话添加背景图片
    C++中的引用
    64位Ubuntu 13.04 安装Bochs 2.3.5
    笔记
    ORG 07C00H的意思
    编译三思
    《黑客与画家》笔记
    linux 2.6up的设备和设备驱动模型
    linux嵌入式系统驱动程序的阻塞与异步
    【转】PWM占空比和分辨率
  • 原文地址:https://www.cnblogs.com/Lyush/p/2612831.html
Copyright © 2011-2022 走看看