题目大意
给定
a
,
b
,
c
,
d
,
k
a,b,c,d,k
a,b,c,d,k,求
∑
i
=
a
b
∑
j
=
c
d
[
(
i
,
j
)
=
k
]
\sum\limits_{i=a}^b\sum\limits_{j=c}^d[(i,j)=k]
i=a∑bj=c∑d[(i,j)=k]
题解
设
f
(
n
,
m
)
=
∑
i
=
1
n
∑
j
=
1
m
[
(
i
,
j
)
=
k
]
f(n,m)=\sum\limits_{i=1}^n\sum\limits_{j=1}^m[(i,j)=k]
f(n,m)=i=1∑nj=1∑m[(i,j)=k]
则
A
n
s
=
f
(
b
,
d
)
−
f
(
a
−
1
,
d
)
−
f
(
b
,
c
−
1
)
+
f
(
a
−
1
,
c
−
1
)
Ans=f(b,d)-f(a-1,d)-f(b,c-1)+f(a-1,c-1)
Ans=f(b,d)−f(a−1,d)−f(b,c−1)+f(a−1,c−1)
f
f
f 的求解见 [POI2007]ZAP-Queries
#include<bits/stdc++.h>
using namespace std;
#define maxn 100000
int mu[maxn],p[maxn];
bool vis[maxn];
void euler_mu(int n) {
int tot=0;
memset(mu,0,sizeof mu);
memset(vis,0,sizeof vis);
mu[1]=1;
for(int i=2;i<=n;++i) {
if(!vis[i]) p[++tot]=i,mu[i]=-1;
for(int j=1;j<=tot&&i*p[j]<=n;++j) {
vis[i*p[j]]=1;
if(i%p[j]==0) {
mu[i*p[j]]=0;
break;
}
mu[i*p[j]]=-mu[i];
}
} for(int i=1;i<=n;i++)
mu[i]+=mu[i-1];
}
int k;
int sol(int _n,int _m){
int ans=0;
_n/=k;_m/=k;
int a=_n,b=_m,n=min(_n,_m);
int len=min(n,min(a,b));
for(int l=1,r;l<=len;l=r+1){
r=min(a/(a/l),b/(b/l));
if(r>n) r=n;
ans+=(mu[r]-mu[l-1])*(a/l)*(b/l);
} return ans;
}
int main(){
int T;euler_mu(50000);
scanf("%d",&T);
while(T--){
int a,b,c,d;
scanf("%d%d%d%d%d",&a,&b,&c,&d,&k);
printf("%d\n",sol(b,d)-sol(a-1,d)-sol(b,c-1)+sol(a-1,c-1));
}
return 0;
}
431

被折叠的 条评论
为什么被折叠?



