题目地址
题意:令x为1到b中的一个数,y为1到d中的一个数,求gcd(x,y)=k的无序对个数,即(x=3,y=5)和(x=5,y=3)这种算同一个。
思路:莫比乌斯经典套路。首先列式子
a
n
s
=
∑
i
=
1
b
∑
j
=
i
d
[
g
c
d
(
i
,
j
)
=
=
k
]
\ ans=\sum_{i=1}^b\sum_{j=i}^d [gcd(i,j)==k]
ans=∑i=1b∑j=id[gcd(i,j)==k](因为是无序对,所以j必须从i开始)
a
n
s
=
∑
i
=
1
⌊
b
k
⌋
∑
j
=
i
⌊
d
k
⌋
[
g
c
d
(
i
,
j
)
=
=
1
]
\ ans=\sum_{i=1}^{\lfloor \frac{b}{k} \rfloor}\sum_{j=i}^{\lfloor \frac{d}{k} \rfloor} [gcd(i,j)==1]
ans=∑i=1⌊kb⌋∑j=i⌊kd⌋[gcd(i,j)==1]
然后后面利用莫比乌斯函数性质
a
n
s
=
∑
i
=
1
⌊
b
k
d
′
⌋
∑
j
=
i
⌊
d
k
d
′
⌋
∑
d
′
∣
g
c
d
(
i
,
j
)
m
u
(
d
′
)
\ ans=\sum_{i=1}^{\lfloor \frac{b}{kd'} \rfloor}\sum_{j=i}^{\lfloor \frac{d}{kd'} \rfloor} \sum_{d'|gcd(i,j)}{mu(d')}
ans=∑i=1⌊kd′b⌋∑j=i⌊kd′d⌋∑d′∣gcd(i,j)mu(d′)
把d’提到前面
a
n
s
=
∑
d
′
=
1
⌊
b
k
⌋
m
u
(
d
′
)
∑
i
=
1
⌊
b
k
d
′
⌋
∑
j
=
i
⌊
d
k
d
′
⌋
1
\ ans=\sum_{d'=1}^{\lfloor \frac{b}{k} \rfloor}{mu(d')}\sum_{i=1}^{\lfloor \frac{b}{kd'} \rfloor}\sum_{j=i}^{\lfloor \frac{d}{kd'} \rfloor}1
ans=∑d′=1⌊kb⌋mu(d′)∑i=1⌊kd′b⌋∑j=i⌊kd′d⌋1
然后就完了,d’是可以直接枚举的,后面显然可以o(1)算出,大概是
令
x
=
⌊
b
k
d
′
⌋
x=\lfloor \frac{b}{kd'} \rfloor
x=⌊kd′b⌋
y
=
⌊
d
k
d
′
⌋
y=\lfloor \frac{d}{kd'} \rfloor
y=⌊kd′d⌋
那么就是
∑
y
−
x
+
1
y
\ \sum_{y-x+1}^y
∑y−x+1y 求和公式就ok了。
因为hdoj在维修,就过了下样例,输出也没按格式,样例是大样例应该没什么问题。
还真有问题,这题k居然可以等于0,记得特判。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <vector>
#include <queue>
#include <set>
#include <stack>
#include <map>
#include <algorithm>
#include <fstream>
using namespace std;
typedef long long ll;
typedef unsigned int uint32;
const int maxn = 3e6 + 100;
const int INF = 0x7fffffff;
const int mod = 1e9+7;
const ll mod1 = 998244353;
const ll base = 137;
const double Pi = acos(-1.0);
const int G = 3;
bool vis1[maxn];
int mu[maxn];
int cnt;
int prime[maxn];
void Init()
{
mu[1] = 1;
cnt = 0;
for(int i=2; i<maxn; i++)
{
if(!vis1[i])
{
prime[cnt++] = i;
mu[i] = -1;
}
for(int j=0; j<cnt&&i*prime[j]<maxn; j++)
{
vis1[i*prime[j]] = 1;
if(i%prime[j]) mu[i*prime[j]] = -mu[i];
else
{
mu[i*prime[j]] = 0;
break;
}
}
}
}
int main()
{
int t;
cin>>t;
int T=1;
Init();
while(t--)
{
int a,b,c,d,k;
scanf("%d%d%d%d%d",&a,&b,&c,&d,&k);
if(k==0)
{
printf("Case %d: ",T++);
puts("0");
continue;
}
if(b>d) swap(b,d);
ll ans=0;
for(int i=1;i<=b/k;i++)
{
int x=b/k/i;
int y=d/k/i;
ans=1ll*ans+1ll*mu[i]*(y-x+1+y)*x/2;
}
printf("Case %d: ",T++);
cout<<ans<<endl;
}
system("pause");
}