题目链接:哆啦A梦传送门
题意:求 ∑ x = a b ∑ y = c d [ g c d ( x , y ) = k ] \begin{aligned} \sum_{x=a}^{b} \sum_{y=c}^{d} [gcd(x,y)=k] \end{aligned} x=a∑by=c∑d[gcd(x,y)=k]
看到这题显然上式等价于 :
∑
x
=
a
b
/
k
∑
y
=
c
d
/
k
[
g
c
d
(
x
,
y
)
=
1
]
\begin{aligned} \sum_{x=a}^{b/k} \sum_{y=c}^{d/k} [gcd(x,y)=1] \end{aligned}
x=a∑b/ky=c∑d/k[gcd(x,y)=1]
这个我们在 bzoj 2190 做过求
∑
x
=
1
n
∑
y
=
1
n
[
g
c
d
(
x
,
y
)
=
1
]
\begin{aligned} \sum_{x=1}^{n} \sum_{y=1}^{n} [gcd(x,y)=1] \end{aligned}
x=1∑ny=1∑n[gcd(x,y)=1],这里也类似。
我们容斥下就可以了 :
我们设
f
(
n
,
m
)
=
∑
x
=
1
n
∑
y
=
1
m
[
g
c
d
(
x
,
y
)
=
1
]
f(n,m)=\begin{aligned} \sum_{x=1}^{n} \sum_{y=1}^{m} [gcd(x,y)=1] \end{aligned}
f(n,m)=x=1∑ny=1∑m[gcd(x,y)=1]
那么此题最终结果就为 :
s
u
m
=
f
(
b
,
d
)
−
f
(
c
−
1
,
b
)
−
f
(
a
−
1
,
d
)
+
f
(
a
−
1
,
c
−
1
)
sum=f(b,d)-f(c-1,b)-f(a-1,d)+f(a-1,c-1)
sum=f(b,d)−f(c−1,b)−f(a−1,d)+f(a−1,c−1)
代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N=5e4+10;
int prime[N],tot,mu[N];
LL sum[N];
bool vis[N];
void init()
{
mu[1]=sum[1]=1;
for(int i=2;i<N;i++)
{
if(!vis[i]){
prime[++tot]=i;
mu[i]=-1;
}
for(int j=1;j<=tot&&i*prime[j]<N;j++){
int x=i*prime[j];
vis[x]=1;
if(i%prime[j]==0){
mu[x]=0;
break;
}
mu[x]=-mu[i];
}
sum[i]=sum[i-1]+mu[i];
}
}
LL solve(int a,int b,int k)
{
LL ret=0;
a=a/k;b=b/k;
if(a>b) swap(a,b);
int r;
for(int l=1;l<=a;l=r+1)
{
r=min(a/(a/l),b/(b/l));
ret=ret+1LL*(sum[r]-sum[l-1])*(a/l)*(b/l);
}
return ret;
}
int main()
{
init();
int a,b,c,d,k;
int ncase;
scanf("%d",&ncase);
while(ncase--){
scanf("%d%d%d%d%d",&a,&b,&c,&d,&k);
LL ret=solve(b,d,k)-solve(c-1,b,k)-solve(a-1,d,k)+solve(a-1,c-1,k);
printf("%lld\n",ret);
}
return 0;
}
我的标签:做个有情怀的程序员。