bzoj3529

# 题解

$\begin{array}{rl}& =\sum _{i=1}^{n}\sum _{j=1}^{m}\sum _{d|gcd\left(i,j\right)}d\\ & =\sum _{d=1}^{n}\sigma \left(d\right)\sum _{i=1}^{n}\sum _{j=1}^{m}gcd\left(i,j\right)==d\\ & =\sum _{d=1}^{n}\sigma \left(d\right)\sum _{i=1}^{⌊\frac{n}{d}⌋}\sum _{j=1}^{⌊\frac{m}{d}⌋}gcd\left(i,j\right)==1\\ & =\sum _{d=1}^{n}\sigma \left(d\right)\sum _{i=1}^{⌊\frac{n}{d}⌋}\sum _{j=1}^{⌊\frac{m}{d}⌋}ϵ\left(gcd\left(i,j\right)\right)\\ & =\sum _{d=1}^{n}\sigma \left(d\right)\sum _{k=1}^{⌊\frac{n}{d}⌋}\mu \left(k\right)⌊\frac{n}{kd}⌋⌊\frac{m}{kd}⌋\end{array}$

$\sigma 、\mu$$\sigma、\mu$都是可以预处理求出来的

# 代码

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define N 100010
int mu[N],sig[N],prime[N],n,tot=0,ms[N],tree[N],ans[N];
bool notprime[N];
struct node{int x,y,a,num;}q[N];
struct node1{int sig,num;}f[N];
bool cmp(node x,node y){return x.a<y.a;}
bool cmp1(node1 x,node1 y){return x.sig<y.sig;}
void mobius(){
mu[1]=1;sig[1]=1;ms[1]=1;
memset(notprime,false,sizeof(notprime));notprime[1]=true;
for(int i=2;i<=100000;i++){
if(!notprime[i]) prime[++tot]=i,mu[i]=-1,sig[i]=i+1,ms[i]=i;
for(int j=1;j<=tot,prime[j]*i<=100000;j++){
notprime[i*prime[j]]=true;
if(i%prime[j]==0){
ms[prime[j]*i]=ms[i]*prime[j];mu[prime[j]*i]=0;
if(ms[i]==i) sig[i*prime[j]]=(i*prime[j]*prime[j]-1)/(prime[j]-1);
else sig[i*prime[j]]=sig[i/ms[i]]*sig[prime[j]*ms[i]];
break;
}mu[i*prime[j]]=-mu[i];sig[i*prime[j]]=sig[i]*sig[prime[j]];ms[i*prime[j]]=prime[j];
}
}
}
for(int i=x;i<=100000;i+=i&-i) tree[i]+=y;
}
int query(int x){
int sum=0;
for(int i=x;i;i-=i&-i) sum+=tree[i];
return sum;
}
void change(int &now,int a){
while(now<=100000 && a>=f[now].sig){
for(int j=1;f[now].num*j<=100000;j++)
now++;
}
}
int solve(int x,int y){
int res=0;if(x>y) swap(x,y);
for(int j=1,last=0;j<=x;j=last+1){
last=min(x/(x/j),y/(y/j));
res+=(query(last)-query(j-1))*(x/j)*(y/j);
}return res&0x7fffffff;
}
int main(){
scanf("%d",&n);mobius();
for(int i=1;i<=100000;i++) f[i].sig=sig[i],f[i].num=i;
sort(f+1,f+100000+1,cmp1);
for(int i=1;i<=n;i++) scanf("%d%d%d",&q[i].x,&q[i].y,&q[i].a),q[i].num=i;
sort(q+1,q+n+1,cmp);
for(int i=1,now=1;i<=n;i++){
change(now,q[i].a);
ans[q[i].num]=solve(q[i].x,q[i].y);
}for(int i=1;i<=n;i++) printf("%d\n",ans[i]&0x7fffffff);
return 0;
}