链接:https://ac.nowcoder.com/acm/contest/634/C
来源:牛客网
题目描述
给出一个区间[L,R],求出[L,R]中 孪生质数有多少对。由于这是一个区间筛质数的模板题。所以小k不屑于去写。
所以出题人只好yy了另一道题。
定义k生互质数为满足y + k与y - k互质的数。
现在给出区间[L,R],你需要输出区间内k生互质数有多少对
我们说一对k生互质数在区间[L,R]内,当且仅当
y+k∈[L,R]y+k∈[L,R]且y−k∈[L,R]y−k∈[L,R]
输入描述:
一行三个数字L,R,k
输出描述:
一行一个数字表示区间[L,R]内的k生互质数的对数
备注:
0≤L,R≤10180≤L,R≤1018
1≤k≤1013
由gcd(x,x+2*k)=gcd(x,2*k)可把问题转化为在区间(l,r-2*k)内有多少个数gcd(x,2*k)等于1;
若两个数求gcd的结果为1,则说明这两个数的最大公因数为1,所以可以将2*k分解质因数并且去重,再使用容斥原理算出区间内有多少个数的因子包含
求出的2*k的质因子;
容斥原理:计算n集合并集的大小,先加上单个集合的大小,再减去所以两个集合相交部分,再加上所以三个集合的相交部分,再减去。。以此类推到n个集合
这题先用分解质因子求出2*k的质因子,再用dfs跑出所有因子的组和
代码如下
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
ll low,high;
ll cnt;
int d;
set<ll>s;
map<ll,int>mp;
map<ll,int>mmp;
void getprim(ll x)
{
for(int i = 2;i <= x;++i)
{
while(x!=i)
{
if(x%i==0)
{
s.insert(i);
x/=i;
}
else
break;
}
}
if(x!=0)
s.insert(x);
}
void dfs(int num,ll mul)
{
set<ll>::iterator ite;
if(mmp[mul])
return;
mmp[mul]=1;
if(num&1)
{
cnt+=high/mul-low/mul;
}
else if(num!=0)
cnt-=high/mul-low/mul;
for(ite=s.begin();ite!=s.end();++ite)
{
if(!mp[*ite])
{
mp[*ite]=1;
dfs(num+1,mul*(*ite));
mp[*ite]=0;
}
}
}
int main()
{
ll l,r,k;
cin>>l>>r>>k;
low=l-1;
high=r-2*k;
if(low<0)
low=0;
if(low>high){
printf("0\n");
return 0;
}
getprim(2*k);
dfs(0,1);
printf("%lld\n",high-low-cnt);
return 0;
}