牛客练习赛44 C:小y的质数

链接:https://ac.nowcoder.com/acm/contest/634/C?tdsourcetag=s_pcqq_aiomsg
来源:牛客网

题目描述

给出一个区间\([L,R]\),求出\([L,R]\)中孪生质数有多少对。
由于这是一个区间筛质数的模板题。所以小k不屑于去写。
所以出题人只好yy了另一道题。
定义\(k\)生互质数为满足\(y + k\)\(y - k\)互质的数。
现在给出区间\([L,R]\),你需要输出区间内\(k\)生互质数有多少对
我们说一对\(k\)生互质数在区间\([L,R]\)内,当且仅当\(y+k \in[L,R]\)\(y-k \in[L,R]\)

输入描述:

一行三个数字\(L,R,k\)

输出描述:

一行一个数字表示区间\([L,R]\)内的\(k\)生互质数的对数
示例1
输入

5 10 1

输出

2

说明
分别为\((5,7),(7,9)\)
示例2
输入

287 11633 10

输出

4532

备注:

\(0 \leq L,R \leq 10^{18}\)

\(1 \leq k \leq 10^{13}\)

思路

\(gcd(y-k,y+k)=1\),令\(x=y-k\),可将\(k\)生互质数转换成:在\([l,r-2\times k]\)范围内,有多少个\(x\),使得\(gcd(x,x+2\times k)=1\)

可以很容易的得到:\(gcd(x,x+2\times k)=gcd(x,2\times k)\),所以该问题就转换成了:在区间\([l,r-2\times k]\)上,有多少个数和\(2\times k\)互质。

接下来,对\(2k\)进行质因子拆分,枚举所有因子,进行容斥即可

代码

#include <bits/stdc++.h>
#define ll long long
#define ull unsigned long long
#define ms(a,b) memset(a,b,sizeof(a))
const int inf=0x3f3f3f3f;
const ll INF=0x3f3f3f3f3f3f3f3f;
const int maxn=1e6+10;
const int mod=1e9+7;
const int maxm=1e3+10;
using namespace std;
map<ll,int>mp;
vector<ll>pri;
ll lcm(ll a,ll b)
{
    return a/__gcd(a,b)*b;
}
void get_prime(ll n)
{
    for(ll i=2;i*i<=n;i++)
    {
        if(n%i==0)
        {
            while(n%i==0)
            {
                if(!mp[i])
                {
                    pri.push_back(i);
                    mp[i]=1;
                }
                n/=i;
            }
        }
    }
    if(n>1)
        pri.push_back(n),mp[n]=1;
}
int main(int argc, char const *argv[])
{
    #ifndef ONLINE_JUDGE
        freopen("/home/wzy/in.txt", "r", stdin);
        freopen("/home/wzy/out.txt", "w", stdout);
        srand((unsigned int)time(NULL));
    #endif
    ios::sync_with_stdio(false);
    cin.tie(0);
    ll l,r,k;
    cin>>l>>r>>k;
    ll K=2*k;
    r-=K;
    if(r<l)
    {
        cout<<0<<endl;
        return 0;
    }
    l=max(l,1LL);
    get_prime(K);
    int sz=pri.size();
    ll ans,ans1;
    ans=ans1=0;
    for(int i=1;i<(1<<sz);i++)
    {
        int cnt=0;
        ll tmp=1;
        for(int j=0;j<sz;j++)
        {
            if(i>>j&1)
            {
                cnt++;
                tmp=lcm(tmp,pri[j]);
            }
        }
        if(cnt&1)
        {
            ans+=(l-1)/tmp;
            ans1+=(r)/tmp;
        }
        else
        {
            ans-=(l-1)/tmp;
            ans1-=r/tmp;
        }
    }
    cout<<r-l+1-ans1+ans<<endl;
    #ifndef ONLINE_JUDGE
        cerr<<"Time elapsed: "<<1.0*clock()/CLOCKS_PER_SEC<<" s."<<endl;
    #endif
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/Friends-A/p/11533510.html