HDU1695 GCD (欧拉函数+容斥原理)

Posted Ritchie丶

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了HDU1695 GCD (欧拉函数+容斥原理)相关的知识,希望对你有一定的参考价值。

求(1,b)区间和(1,d)区间里面gcd(x, y) = k的数的对数(1<=x<=b , 1<= y <= d)。

b和d分别除以k之后的区间里面,只需要求gcd(x, y) = 1就可以了,这样子求出的数的对数不变。

这道题目还要求1-3 和 3-1 这种情况算成一种,因此只需要限制x<y就可以了

 

只需要枚举x,然后确定另一个区间里面有多少个y就可以了。因此问题转化成为区间(1, d)里面与x互素的数的个数

先求出x的所有质因数,因此(1,d)区间里面是x的质因数倍数的数都不会与x互素,因此,只需要求出这些数的个数,减掉就可以了。

如果w是x的素因子,则(1,d)中是w倍数的数共有d/w个。

 

容斥原理:

所有不与x互素的数的个数= 1个因子倍数的个数 - 2个因子乘积的倍数的个数 + 3个……-……

 

答案很大,用long long。

所有数的素因子,预先处理保存一下,不然会超时的。

#include<iostream>
using namespace std;
const int Max=100005;
__int64 elur[Max];//存放每个数的欧拉函数值
int num[Max];//存放数的素因子个数
int p[Max][20];//存放数的素因子
void init()//筛选法得到数的素因子及每个数的欧拉函数值
{
    elur[1]=1;
    for(int i=2;i<Max;i++)
    {
        if(!elur[i])
        {
            for(int j=i;j<Max;j+=i)
            {
                if(!elur[j])
                    elur[j]=j;
                elur[j]=elur[j]*(i-1)/i;
                p[j][num[j]++]=i;
            }
        }
        elur[i]+=elur[i-1]; //进行累加(法里数列长度)
    }
}
int dfs(int idx,int b,int now)//求不大于b的数中,与now不互质的数的个数;
{                                //dfs()写的容斥原理
    int ans=0;
    for(int i=idx;i<num[now];i++)//容斥原理来求A1并A2并A3.....并Ak的元素的数的个数.
        ans += b/p[now][i]-dfs(i+1,b/p[now][i],now);
    return ans;
}

int main()
{
    int t,a,b,c,d,k;
    init();
    scanf("%d",&t);
    for(int ca=1;ca<=t;ca++)
    {
        scanf("%d%d%d%d%d",&a,&b,&c,&d,&k);
        printf("Case %d: ",ca);
        if(k==0)
        {
            printf("0\n");
            continue;
        }
        if(b>d)
            swap(b,d);
        b/=k;  d/=k;
        __int64 ans=elur[b];
        for(int i=b+1;i<=d;i++)
            ans+=b-dfs(0,b,i);//求不大于b的数中,与i不互质的数的个数
        printf("%I64d\n",ans);
    }
    return 0;
}

 

以上是关于HDU1695 GCD (欧拉函数+容斥原理)的主要内容,如果未能解决你的问题,请参考以下文章

HDU1695-GCD(数论-欧拉函数-容斥)

hdu 1695 GCD 欧拉函数 + 容斥

GCD HDU - 1695 (容斥原理)

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

GCD HDU - 1695 (欧拉 + 容斥)

GCD HDU - 1695(容斥原理)