HDU-1695 GCD(求一个区间内与一个数互质的个数)

Posted Cherry93

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了HDU-1695 GCD(求一个区间内与一个数互质的个数)相关的知识,希望对你有一定的参考价值。

题意:

  给你一个T,是样例的个数,接下来是五个数l1,r1,l2,r2,k  前四个数代表两个区间(l1,r1),(l2,r2)这个题l1=1,l2=1; 

取x1属于(1,r1),x2属于(1,r2);

  求使得gcd(x1,x2)==k 的(x1,x2)的个数,特别的(1,2)和(2,1)只计算一次;

思路:

  他让求gcd等于k的   我们可以让r1,r2都除以k相当于求               取x1属于(1,r1/k),x2属于(1,r2/k);  求使得gcd(x1,x2)==1 的(x1,x2)的个数,就相当于求两个区间内互质的数可以组成几组

 

那么 这个题就简单了,,套上求一个区间内与一个数互质的个数的模板就A了

 

AC代码如下;

  

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <map>
#include <cmath>
using namespace std;
typedef long long ll;
const int maxn=1e6+5;
vector<ll> p[maxn];
void getpri(ll kk)//这里先把每个数的素因子筛选出来,,因为这个题数据大,需要预处理一下1到1e5的素因子,防止超时
{
    ll x=kk;
    for(ll i=2;i*i<=x;i++)
    {
        if(x%i==0)
        {
            p[kk].push_back(i);
            while(x%i==0)
                x/=i;
        }
    }
    if(x>1)p[kk].push_back(x);
}
ll solve(ll x,ll r)//这里就是求一个区间内的与一个数互质的个数的模板;
{

    ll ans=0;
    for(ll i=1;i<(1<<p[x].size());i++)
    {
        ll cnt=0;
        ll mult=1;
        for(ll j=0;j<p[x].size();j++)
        {
            if(i&(1<<j))
            {
                cnt++;
                mult*=p[x][j];
            }
        }  mult=r/mult;
        if(cnt&1)
            ans+=mult;
        else ans-=mult;
    }
    if(ans<0)ans=0;
    if(r-ans<0)return 0;
    return r-ans;
}
int main()
{
    int T,t=1;
    for(int i=1;i<maxn;i++)
        getpri(i);
    scanf("%d",&T);

    while(T--)
    {
        ll l1,r1,r2,l2,k;
        scanf("%lld%lld%lld%lld%lld",&l1,&r1,&l2,&r2,&k);
        if(k==0)//特别要注意这个题一个坑点,,k可能等于0!!!!!!!!
        {
            printf("Case %d: 0\\n",t++);
            continue;
        }
        r1/=k;r2/=k;
        ll ans=0;
        if(r1>r2)swap(r1,r2);//找出大区间
        for(ll i=1;i<=r2;i++)//这里遍历大区间,对于每个小于等于r1的数x1先求一下小于等于x1的与x1互质的个数,之后的x2>r1  求(1,r1)区间内与x2互质的个数
{
       //比如(1,5),(1,10)
       //先求(1,1)内和1互质的个数,再求(1,2)内与2互质的个数,再求(1,3)与3,再求(1,4)与4,再求(1,5)与5,后面的就是求6,7,8,9,10分别与(1,5)内互质的个数
            ans+=solve(i,min(i,r1));
        }
        printf("Case %d: %lld\\n",t++,ans);
    }
    return 0;
}

 

 

这个题还有另一种模板,就是深搜模板想了解一下的朋友详见

https://www.cnblogs.com/1013star/p/9896262.html

以上是关于HDU-1695 GCD(求一个区间内与一个数互质的个数)的主要内容,如果未能解决你的问题,请参考以下文章

hdu 1695 GCD 欧拉函数 + 容斥

GCD HDU - 1695(容斥原理)

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

HDU 1695 GCD(莫比乌斯反演)

hdu1695 GCD(莫比乌斯反演)

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