Given 5 integers: a, b, c, d, k, you’re to find x in a…b, y in c…d that GCD(x, y) = k. GCD(x, y) means the greatest common divisor of x and y. Since the number of choices may be very large, you’re only required to output the total number of different number pairs.
Please notice that, (x=5, y=7) and (x=7, y=5) are considered to be the same.
Yoiu can assume that a = c = 1 in all test cases.
Input
The input consists of several test cases. The first line of the input is the number of the cases. There are no more than 3,000 cases.
Each case contains five integers: a, b, c, d, k, 0 < a <= b <= 100,000, 0 < c <= d <= 100,000, 0 <= k <= 100,000, as described above.
Output
For each test case, print the number of choices. Use the format in the example.
Sample Input
2
1 3 1 5 1
1 11014 1 14409 9
Sample Output
Case 1: 9
Case 2: 736427
Hint
For the first sample input, all the 9 pairs of numbers are (1, 1), (1, 2), (1, 3), (1, 4), (1, 5), (2, 3), (2, 5), (3, 4), (3, 5).
这题写的是与gcd有关但是,实际上做起来,没有关系,
实际上先看一组范围比如1到10的范围,然后k为2,那么1到10 里的数至少得是2的倍数,我们可以表示成num=2a,可以看a和2都是num的因子,而2a必须小于10,那么我们可以枚举a这个因子,这个a的上界就是10/2
枚举1到5就是相当与枚举了1到10并且是是可以整除k的数;
所有题目转化成求 1 b/k 1 d/k 1的合法可能
因为我们要求(x,y)和(y,x)是同一种,所假设x<y,那么去枚举y,在小于另一个范围去找所有与y互质的数;
我在1到6假设枚举了6,这里我们用减法,那么假设1到3都满足,我们减去不互质的情况,这里就需要容斥原理的知识,比如6的因子有2和3,那么假设另一个范围是1到5,那么我需要找出1到5里所有与6不互质也就是带有2和3因子的数,那么这里容斥思想是,对于是2的倍数的所有数是一个集合s2,对所有是3的倍数是一个集合s3,而是2并且是3的倍数又是一个集合s23
所以应该s2+s3-s23
#include<cstdio>
#include<cstring>
#include<algorithm>
#include <iostream>
#include<cmath>
#include <string>
#include<vector>
#define N 100000
using namespace std;
vector<int> dit[100002];
bool pri[100002];
void prime()//这个用来枚举每个数的因子
{
memset(pri,true,sizeof(pri));
for(int i=2;i<=N;i++)
if(pri[i])
{
for(int j=i;j<=N;j+=i)
{
pri[j]=false;
dit[j].push_back(i);
}
}
}
int get(int limit,int state,int num)//state是一个2进制形式的状态,用来枚举这个数的因子组合
{
int o=1;
int count=0;
for(int i=0;i<dit[num].size();i++)
{
if((1<<i)&state)
{
count++;
o*=dit[num][i];//得出在state这个组合下的数
}
}
int ans=limit/o;//那么这个就是在limit范围下的这个state集合的个数
if(count%2==0)return -ans;//查看这个集合是多少个单个集合的交际,如果偶数就减去,反之加上
else return ans;
}
int main()
{
int b,d,k;
int l;
int n;
prime();
scanf("%d",&n);
int t=1;
while(n--)
{
scanf("%d%d%d%d%d",&l,&b,&l,&d,&k);
if(!k)//特殊情况考虑
{
printf("Case %d: %d\n",t++,0);
continue;
}
d/=k;
b/=k;
if(b>d)
{
int temp=b;
b=d;
d=temp;
}
int limit;
long long ans=0;
for(int i=1;i<=d;i++)
{
limit=min(i,b);
ans+=limit;//加上总的,在由下面的枚举减去不合法的个数
for(int s=1;s<(1<<(dit[i].size()));s++)
ans-=get(limit,s,i);
}
printf("Case %d: %lld\n",t++,ans);
}
return 0;
}