题解:
反演,按a从小到大排序,依次加入符合题意的f(d)值;
用树状数组维护前缀和
注意:
取模时做差注意负数
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long Lint;
const int maxQ=20009;
const int maxn=100009;
const Lint mm=(1LL<<31);
int T;
Lint ans[maxn];
struct questions{
int n,m,a,idx;
}q[maxQ];
int cmp(const questions &tmp1,const questions &tmp2){
return tmp1.a<tmp2.a;
}
Lint f[maxn];
Lint g[maxn];
int d[maxn];
int cmp2(const int &tmp1,const int &tmp2){
if(f[tmp1]<f[tmp2])return 1;
else return 0;
}
int vis[maxn]={0};
int prime[maxn],cntprime;
int mu[maxn];
int r[maxn];
int prepro(){
vis[1]=1;mu[1]=1;
for(int i=2;i<=100000;++i){
if(!vis[i]){
prime[++cntprime]=i;
mu[i]=-1;
}
for(int j=1;j<=cntprime&&i*prime[j]<=100000;++j){
vis[i*prime[j]]=1;
if(i%prime[j]==0){
mu[i*prime[j]]=0;
break;
}
mu[i*prime[j]]=-mu[i];
}
}
for(int i=2;i<=100000;++i)mu[i]+=mu[i-1];
for(int d=1;d<=100000;++d){
for(int k=1;k*d<=100000;++k){
f[d*k]=(f[d*k]+d)%mm;
}
}
for(int i=1;i<=100000;++i)r[i]=i;
sort(r+1,r+1+100000,cmp2);
}
Lint c[maxn];
inline int lowbit(int x){
return x&(-x);
}
int add(int x,Lint val){
while(x<=100000){
c[x]=(c[x]+val)%mm;
x+=lowbit(x);
}
}
Lint query(int x){
Lint ret=0;
while(x){
ret=(ret+c[x])%mm;
x-=lowbit(x);
}
return ret;
}
int minit(){
memset(f,0,sizeof(f));
memset(g,0,sizeof(g));
memset(c,0,sizeof(c));
cntprime=0;
}
int main(){
minit();
prepro();
scanf("%d",&T);
for(int i=1;i<=T;++i){
scanf("%d%d%d",&q[i].n,&q[i].m,&q[i].a);
q[i].idx=i;
}
sort(q+1,q+1+T,cmp);
int head=0;
for(int i=1;i<=T;++i){
while((head<100000)&&(f[r[head+1]]<=q[i].a)){
int v=r[++head];
for(int k=1;k*v<=100000;++k){
add(k*v,f[v]*(mu[k]-mu[k-1]));
}
}
int n=q[i].n;
int m=q[i].m;
int a=q[i].a;
if(n>m)swap(n,m);
Lint ret=0;
int last;
for(int j=1;j<=n;j=last+1){
last=min(n/(n/j),m/(m/j));
ret=ret+(query(last)-query(j-1)+mm)*1LL*(n/j)*(m/j);
ret=ret%mm;
}
ans[q[i].idx]=ret;
}
for(int i=1;i<=T;++i){
printf("%lld\n",ans[i]);
}
return 0;
}