HDU - 1695 GCD (容斥原理)
http://acm.hdu.edu.cn/showproblem.php?pid=1695
题目大意:
给你 a b c d k
让你从 (a,b)中选一个x (c,d) 中选一个y 保证 gcd(x,y) =k
并且 (3,5) (5,3) 视为一种选择。
问:有多少种选择
解题思路:
gcd(x,y) = k 那我们可以让b和d同时/k
就可以化简为 求(1,b) (1,d)中互质的数的个数。
就可以用这个题的思路:HDU - 4135 Co-prime
https://blog.youkuaiyun.com/weixin_43179892/article/details/98237974
这里还有一个问题 就是重复的问题。怎么去重呢?
看第一个样例。 我们 i 遍历(1,3) 求 i 与(1,5)中互质的个数。那么(1.3)中互质的数的个数就多加了一遍,因此我们减去一半(1-3)中和(1-3)中互质的对数一半 就是答案。
注意:k==0时直接输出0 因为没有数的gcd == 0
AC代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#define ll long long
using namespace std;
const int maxn = 1e5+10;
int p[maxn];
int num = 0;
ll gcd(ll a,ll b){
if(b==0) return a;
else{
return gcd(b,a%b);
}
}
ll lcm(ll a,ll b){
return a*b/gcd(a,b);
}
//对k分解质因数
void pr(int k){
num = 0;
for(int i=2;i*i<=k;i++){
if(k%i==0){
p[num++] = i;
while(k%i==0){
k/=i;
}
}
}
if(k>1) p[num++] = k;
}
ll ans = 0;
/// 1-N 中有多少和k不互质的
void dfs(int th,int time,ll now,ll N){
if(time>num) return;
ll lcc = lcm(now,p[th]);
if(time&1) ans+=(N/lcc);
else ans -= (N/lcc);
for(int i=th+1;i<num;i++){
dfs(i,time+1,lcc,N);
}
}
///1-n中和k互质的数的个数
ll solve(ll k,ll n){
pr(k);
ans = 0;
for(int i=0;i<num;i++){
dfs(i,1,p[i],n);
}
return n-ans;
}
int main(){
int cas = 1;
int t;
cin>>t;
ll a,b,c,d,k;
while(t--){
scanf("%lld%lld%lld%lld%lld",&a,&b,&c,&d,&k);
if(k==0||k>b||k>d){
printf("Case %d: 0\n",cas++);
continue;
}
b/=k;
d/=k;
ll res = 0;
for(ll i=1;i<=b;i++){
res += solve(i,d);
}
int mm = min(b,d);
ll ss = 0;
for(int i=1;i<=mm;i++){
ss += solve(i,mm);
}
res = res - ss/2;
printf("Case %d: %lld\n",cas++,res);
}
return 0;
}