popoqqq大爷有一份不错的题解.
这题是道挺好的莫比乌斯练习题.
做这种类型的题目最需要注意的是理清思路,否则很容易陷进去出不来.
找一个数的因数不是很容易(n0.5),但是我想从它的因数找到它却很容易(均摊logn).
需要注意求和符号的变换.
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<ctime>
#include<cmath>
#include<algorithm>
#include<queue>
#include<set>
#include<map>
#include<iomanip>
using namespace std;
#define LL long long
#define up(i,j,n) for(int i=j;i<=n;i++)
#define pii pair<LL,LL>
#define db double
#define eps 1e-4
#define FILE "dealing"
LL read(){
LL x=0,f=1,ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch<='9'&&ch>='0'){x=(x<<1)+(x<<3)+ch-'0',ch=getchar();}
return x*f;
}
const LL maxn=401000,inf=1000000000000000LL,limit=(LL)(1e5+0.5),mod=1000000007;
bool cmin(LL& a,LL b){return a>b?a=b,true:false;}
bool cmax(LL& a,LL b){return a<b?a=b,true:false;}
struct node{
int n,m,a,id,ans;
}a[maxn];
bool cmp(node a,node b){return a.id<b.id;}
bool cmp2(node a,node b){return a.a<b.a;}
int F[maxn],f[maxn],q,prime[maxn],b[maxn],mu[maxn],tail=0;
void getmu(){
mu[1]=1;
for(int i=2;i<=limit;i++){
if(!b[i])prime[++tail]=i,mu[i]=-1;
for(int j=1;j<=tail&&prime[j]*i<=limit;j++){
b[i*prime[j]]=1;
if(i%prime[j])mu[i*prime[j]]=-mu[i];
else {mu[i*prime[j]]=0;break;}
}
}
}
int c[maxn];
int lowbit(LL x){return x&-x;}
void add(LL x,LL d){
while(x<=limit){
c[x]+=d;
x+=lowbit(x);
}
return;
}
int getsum(LL x){
LL ans=0;
while(x){
ans+=c[x];
x-=lowbit(x);
}
return ans;
}
pii t[maxn];
int main(){
freopen(FILE".in","r",stdin);
freopen(FILE".out","w",stdout);
up(i,1,limit)for(int j=1;j*i<=limit;j++)
f[i*j]+=i;//求出因数和
up(i,1,limit)t[i].first=f[i],t[i].second=i;
sort(t+1,t+limit+1);
getmu();//求mu函数
q=read();
up(i,1,q){
a[i].n=read(),a[i].m=read(),a[i].a=read();
a[i].id=i;
if(a[i].n>a[i].m)swap(a[i].n,a[i].m);
}//init
sort(a+1,a+q+1,cmp2);
int last=1;
for(int i=1;i<=q;i++){
int A=a[i].a;
for(int j=last;t[j].first<=A;j++){
for(int k=1;k*t[j].second<=limit;k++)
add(k*t[j].second,t[j].first*mu[k]);
last=j+1;
}
int ans=0,pos=0,n=a[i].n,m=a[i].m;
for(int j=1;j<=a[i].n;j++){
pos=min(n/(n/j),m/(m/j));
ans+=(n/j)*(m/j)*(getsum(pos)-getsum(j-1));
j=pos;
}
a[i].ans=ans;
}
sort(a+1,a+q+1,cmp);
up(i,1,q)printf("%d
",a[i].ans&((1LL<<31)-1));
return 0;
}