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; }