很久很久以前,我认为容斥原理的公式是无法实现的,因为那个公式又臭又长,实际使用时又有许多限制。
现在我才知道真的是可以写的。
之后我有可能写《离散数学》心得时候写容斥原理,这里接着这个题记录一下对容斥新的认识。
题如下:
链接:https://ac.nowcoder.com/acm/contest/634/C
来源:牛客网
时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 262144K,其他语言524288K
64bit IO Format: %lld
题目描述
给出一个区间[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生互质数的对数
示例1
输入
5 10 1
输出
2
说明
分别为(5,7),(7,9)
示例2
输入
287 11633 10
输出
4532
备注:
0≤L,R≤1018
1≤k≤1013
这里数据范围搞得很乱,推荐去原链接看题。
题目想要两个数互质既 gcd(y-k,y+k)=1, 这里 令 x=y-k 那么 我们要找 gcd(x,x+2k)=1的x。
这里 L<=x<=R-2k。
很好证明, gcd(x,x+2k)=gcd(x,2k)。
那么 x与2k 互质时,x与x+2k互质。我们要在 L~R-2k中寻找x使得gcd(x,2k)=1。
对2k进行质因数分解,寻找区间中质因子不包含任何2k质因数的数。
这个时候我们就必须用到容斥原理了,相信大家又不是山顶洞人,我就不过多解释啥是容斥了,贴个公式吧。可以百度百科
下面是代码
#include<stdio.h>
#include<iostream>
#include<math.h>
using namespace std;
typedef long long ll;
ll prim[100]={0},con=0;
ll num(ll t){ //容斥原理
if(t<0) return 0;
ll res=0;
ll i,j;
for(i=0;i<(1<<con);i++){ //用i来表示质因数选择的每一种可能性
ll p=1,f=1; //f来表示这个可能性的符号
for(j=0;j<con;j++){ //用j来搜索i当中的质数
if((1<<j)&i){
p=p*prim[j];
f=f*(-1);
}
}
res=res+(t/p)*f; //一开始res加上集合中所有元素的数量,然后减去容斥的数量。
}
return res;
}
int main(){
ll k,r,l,i;
cin>>l>>r>>k;
k=k*2;
r=r-k;
if((l+k)>r){
printf("0\n");
return 0;
}
ll s=sqrt(k);
for(i=2;i<s;i++){
if(k%i==0)
prim[con++]=i;
while(k%i==0) k=k/i;
}
if(k!=1)
prim[con++]=k;
cout<<num(r)-num(l-1)<<endl;
return 0;
}