您的位置:首页 > 其它

HDU 1695 莫比乌斯反演

2015-04-13 18:03 239 查看
题目大意:

从1~b中取一个数作为x , 1~d中取一个数作为y

令gcd(x,y) = k 的取法有多少种

这里我们可以用莫比乌斯函数来解决问题

这里用到的公式是[gcd(x,y)==1] = Σ(del|gcd(x,y))mu(del)

Σ(1<=x<=b)Σ(1<=y<=d)[gcd(x,y)==k]

= Σ(1<=x<=b/k)Σ(1<=y<=d/k)[gcd(x,y)==1]

= Σ(1<=x<=b/k)Σ(1<=y<=d/k) Σ(del|gcd(x,y)) mu(del)

=Σ(1<=x<=b/k & del|x)Σ(1<=y<=d/k & del|y) mu(del)

#include <cstdio>
#include <cstring>
#include <iostream>

using namespace std;
#define ll long long
#define N 100010
int mu
, prime
;
bool check
;

void getMu(int n)
{
memset(check , 0 , sizeof(check));
mu[1] = 1;
int tot = 0;
for(int i=2 ; i<=n ; i++){
if(!check[i]){
prime[tot++]=i;
mu[i] = -1;
}
for(int j=0 ; j<tot ; j++){
if(i*prime[j]>n) break;
check[i*prime[j]] = true;
if(i % prime[j] == 0){
mu[i*prime[j]] = 0;
break;
}else{
mu[i*prime[j]] = -mu[i];
}
}
}
}

int main()
{
int a , b , c , d , k , T , cas=0;
scanf("%d" , &T);
getMu(100000);
while(T--)
{
scanf("%d%d%d%d%d" , &a , &b , &c , &d , &k);
if(k == 0){
printf("Case %d: 0\n" , ++cas);
continue;
}
a/=k , b/=k , c/=k , d/=k;
int maxn = b;
if(b<d){
int t=b;
b=d , d=t;
maxn = b;
}
ll ans = 0;
for(int i=1 ; i<=maxn ; i++){
int t1 = b/i , t2=d/i;
ans = ans+(ll)t1*t2*mu[i];
}

//计算重复的
ll tmp = 0;
for(int i=1 ; i<=maxn ; i++){
int t1 = d/i , t2 = d/i;
tmp = tmp+(ll)t1*t2*mu[i];
}
ans = ans - (tmp-1)/2;
printf("Case %d: %lld\n" , ++cas , ans);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: