• 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
    ",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
    ",t++,ans);
        }
        return 0;
    }

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

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

  • 相关阅读:
    C# 字符串转换值类型
    C#判断字符串为空
    c#转义字符
    python各种类型的转换
    mysql创建新用户及新用户不能本地登陆的问题
    数据探索的方法
    使用requests爬取猫眼电影TOP100榜单
    Python中的正则表达式教程
    Anaconda多版本Python管理以及TensorFlow版本的选择安装
    Xshell访问虚拟机内Linux
  • 原文地址:https://www.cnblogs.com/Cherry93/p/9897618.html
Copyright © 2020-2023  润新知