• hdu 1695 GCD(欧拉函数+容斥原理)


    http://acm.hdu.edu.cn/showproblem.php?

    pid=1695

    非常经典的题。同一时候感觉也非常难。

    在区间[a,b]和[c,d]内分别随意取出一个数x,y,使得gcd(x,y) = k。问这种(x,y)有多少对。能够觉得a,c均为1,并且gcd(5,7)与gcd(7,5)是同一种。


    由于gcd(x,y) = k,那么gcd(x/k,y/k) = 1。也就是求区间[1,b/k]和[1,d/k]内这种(x,y)对使得gcd(x,y) = 1。

    为了防止计数反复,首先假定b/k <= d/k,那么当y <= b/k时。这种对数有Euler[y]个。当y > b/k时,先把y进行素因子分解为p1,p2...pi。仅仅要可以求出[1,b/k]内与y不互质的数,那么与y互质的数用b减去就行了。求与y不互质的数的个数用到容斥原理。由于某些素因子的倍数是一样的,令pi的整数倍集合为Ai,那么就是求这些集合的并。

    求集合的并依据容斥关系进行dfs。

    这个想了好久没有想出来,參考了某大神的博客写出来的。大体思路就是如果素因子分解出来是p1,p2,p3,先把仅仅有p1倍数的个数求出来。这是一个递归的过程。即是p1倍数的个数减去p1p2倍数的个数减去p1p2p3倍数的个数,相同的对于p2,p2倍数的个数减去p2p3倍数的个数。


    #include <stdio.h>
    #include <iostream>
    #include <map>
    #include <set>
    #include <list>
    #include <stack>
    #include <vector>
    #include <math.h>
    #include <string.h>
    #include <queue>
    #include <string>
    #include <stdlib.h>
    #include <algorithm>
    //#define LL long long
    #define LL __int64
    #define eps 1e-12
    #define PI acos(-1.0)
    #define C 240
    #define S 20
    using namespace std;
    const int maxn = 100010;
    
    int flag[maxn];
    int prime[maxn];
    int phi[maxn];
    vector <int> edge[maxn];
    int test,a,b,c,d,k;
    
    //基于素数筛的欧拉函数
    void init()
    {
        memset(flag,0,sizeof(flag));
        prime[0] = 0;
        phi[1] = 1;
        for(int i = 2; i < maxn; i++)
        {
            if(flag[i] == 0)
            {
                prime[++prime[0]] = i;
                phi[i] = i-1;
            }
            for(int j = 1; j <= prime[0] && prime[j]*i < maxn; j++)
            {
                flag[prime[j]*i] = 1;
                if(i % prime[j] == 0)
                    phi[prime[j]*i] = phi[i]*prime[j];
                else phi[prime[j]*i] = phi[i]*(prime[j]-1);
            }
        }
    }
    
    //vector存每一个数的素因子。
    void spilt()
    {
        for(int i = 1; i < maxn; i++)
        {
            int tmp = i;
            for(int j = 1; prime[j]*prime[j] <= tmp; j++)
            {
                if(tmp % prime[j] == 0)
                {
                    edge[i].push_back(prime[j]);
                    while(tmp % prime[j] == 0)
                        tmp /= prime[j];
    
                }
                if(tmp == 1)
                    break;
            }
            if(tmp > 1)
                edge[i].push_back(tmp);
        }
    }
    
    //求小于等于b的与cur不互质的数的个数
    LL dfs(int st, int b, int cur)
    {
        LL res = 0;
        for(int i = st; i < (int)edge[cur].size(); i++)
        {
            int k = b/edge[cur][i];
            res += k - dfs(i+1,k,cur);
        }
        return res;
    }
    
    int main()
    {
        init();
        spilt();
        
        scanf("%d",&test);
        for(int item = 1; item <= test; item++)
        {
            scanf("%d %d %d %d %d",&a,&b,&c,&d,&k);
            if(k == 0 || k > b || k > d)
            {
                printf("Case %d: 0
    ",item);
                continue;
            }
            b /= k;
            d /= k;
            if(b > d)
                swap(b,d);
            LL ans = 0;
            for(int i = 1; i <= b; i++)
            {
                ans += phi[i];
            }
            for(int i = b+1; i <= d; i++)
            {
                ans += b-dfs(0,b,i);
            }
            printf("Case %d: %I64d
    ",item,ans);
    
        }
        return 0;
    }
    




  • 相关阅读:
    【UWP】使用Action代替Command
    【UWP】在不同类库使用ResourceDictionaries
    【UWP】不通过异常判断文件是否存在
    【UWP】批量修改图标尺寸
    【UWP】FlipView绑定ItemsSource,Selectedindex的问题
    【UWP】UI适配整理
    【iOS】Object-C注释
    【iOS】desctiption和debugDescription
    【iOS】关联属性存取数据
    【iOS】配置和使用静态库
  • 原文地址:https://www.cnblogs.com/zhchoutai/p/7067023.html
Copyright © 2020-2023  润新知