您的位置:首页 > 其它

HDU-1695-GCD(Mobius反演/容斥)

2016-04-19 18:21 316 查看
[align=left]Sample Input[/align]

2
1 3 1 5 1
1 11014 1 14409 9


[align=left]Sample Output[/align]

Case 1: 9
Case 2: 736427

HintFor 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).


题意:a,b,c,d,m, 0<=x<=b,0<=y<=d,求满足gcd(x,y)=m这样的数对(x,y)的数量 

题解:



CODE:

#include <iostream>
#include <cstdio>
#include <vector>
#include <algorithm>
#include <cstring>
#include <string>
#include <cmath>
#include <set>
#include <map>
#include <queue>
#include <stack>
using namespace std;
#define LL long long

const int N = 100010;
int mu
;
void getMu()
{
for (int i = 1; i < N; ++i)
{
int target = i == 1 ? 1 : 0;
int delta = target - mu[i];
mu[i] = delta;
for (int j = 2 * i; j < N; j += i)
mu[j] += delta;
}
}
bool check
;
int prime
;
void Moblus()
{
memset(check,false, 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[prime[j]*i] =true;
if(i%prime[j]==0)
{
mu[i*prime[j]]=0;
break;
}
else
mu[i*prime[j]]=-mu[i];
}
}
}
int a,b,c,m;
int main()
{
//getMu();
Moblus();
int T;
scanf("%d", &T);
int cas=1;
while(T--)
{
scanf("%d%d%d%d%d",&c,&a,&c,&b,&m);
if(m==0){printf("Case %d: 0\n",cas++);continue;}
if(a>b)swap(a,b);
LL ans=0;
a/=m,b/=m;
for(int i=1; i<=a; ++i)
ans-=(LL)mu[i]*(a/i)*(a/i);
ans/=2;
for(int i=1; i<=a; ++i)
ans+=(LL)mu[i]*(a/i)*(b/i);
printf("Case %d: %I64d\n",cas++,ans);
}
return 0;
}


另外容斥解法:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#include <cmath>
#include <set>
#include <vector>
#define INF 0x3f3f3f3f
using namespace std;
#define N 100005

int a,b,c,k,mod;
vector<int> x
;
bool is
;
void get_prime()
{
memset(is,0,sizeof(is));
for(int i=0; i<N; ++i)
x[i].clear();
for(int i=2; i<N; i+=2)x[i].push_back(2);
for(int i=3; i<N; i+=2)
if(!is[i])
{
for(int j=i; j<N; j+=i)
{
is[j]=1;
x[j].push_back(i);
}
}
}
long long solve(long long m, long long n)
{
long long sum=0;
for(int i=1; i<1<<x
.size(); ++i)
{
int cnt=0;
int val=1;
for(int j=0; j<x
.size(); ++j)
{
if(i&(1<<j))
{
val*=x
[j];
++cnt;
}
}
if(cnt&1)sum+=m/val;
else sum-=m/val;
}
return m-sum;
}
int main()
{
int T;
get_prime();
scanf("%d",&T);
int cas=1;
while(T--)
{
long long ans=0;
scanf("%d%d%d%d%d",&c,&a,&c,&b,&k);
if (k == 0)
{
printf("Case %d: 0\n", cas++);
continue;
}
a/=k;
b/=k;
if(a>b)swap(a,b);
for(int i=1; i<=b; ++i)
//for(int j=1; j<=i&&j<=a; ++j)
{
ans+=solve(min(i,a),i);
}
printf("Case %d: %I64d\n",cas++,ans);
//cout<<ans<<endl;
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: