GCD
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.
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.
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.
2 1 3 1 5 1 1 11014 1 14409 9
Sample Output
Case 1: 9
Case 2: 736427
思路: gcd(m,n) = k 即 gcd(m/k, n/k) = 1
问题变成{gcd(s,t)=1| s∈(1,b/k)且t∈(1,d/k)}
可以转化为 枚举每一个s∈(1,b/k) 计算 1~d/k中有多少与其互质的数. 互质数的个数不好求, 但不互质的数可以枚举质因数容斥来计算.
由于Case较多, 所以对1e5以下的每个数的质因数进行预处理.
代码如下:
#include<iostream>
#include<algorithm>
#include<cmath>
#include<vector>
#include<queue>
#include<iomanip>
#include<stdlib.h>
#include<cstdio>
#include<string>
#include<string.h>
#include<set>
#include<map>
using namespace std;
typedef long long ll;
typedef pair<int,int> P;
const int INF = 0x7fffffff;
const int MAX_N = 1e5+5;
const int MAX_V = 0;
const int MAX_M = 0;
const int MAX_Q = 0;
const int M = 100000;
void show(string a, int val){
cout<<a<<": "<<val<<endl;
}
//Define array zone
int a, b,c ,d, k;
bool used[MAX_N];
vector<int> G[MAX_N];
int p = 0, x;
int prime[MAX_N];
//Cut-off rule
ll gcd(ll a, ll b){
if(b==0) return a;
return gcd(b, a%b);
}
void init(){
// seek prime factor
for(int i=2; i<=M; i++){
if(!used[i]){
prime[p++] = i;
for(int j=2; i*j<=M; j++){
used[i*j] = true;
}
}
}
prime[p] = INF;
// find the prime factor of intergers not larger than M
for(int i=2; i<=M; i++){
int tmp = i;
for(int j=0; prime[j]<=tmp&&tmp!=1; j++){
int pr = prime[j];
if(tmp%pr==0) G[i].push_back(pr);
while(tmp%pr==0) tmp/=pr;
}
}
}
ll calc(int t){
int k = G[t].size();
ll res = 0;
for(int i=1; i<1<<k; i++){
int num = 0;
for(int j=i; j!=0; j>>=1) num += j&1;
ll lcm = 1;
for(int j=0; j<k; j++){
if(i>>j&1) lcm = lcm/ gcd(lcm, G[t][j]) *G[t][j];
if(lcm>d) break;
}
int sym = num&1? 1: -1;
res += sym * (d-t) /lcm;
}
return res;
}
void solve(){
ll res = 0;
if(k!=0){
b /= k; d /= k;
if(b>d) swap(b,d);
if(b>0)
res += d;
for(int i=2; i<=b; i++){
res += (d - i) - calc(i);
}
}
cout<<"Case "<<++x<<": "<<res<<endl;
}
int main(){
init();
int T; scanf("%d",&T);
while(T--){
scanf("%d%d%d%d%d",&a,&b,&c,&d,&k);
solve();
}
}