题解:
反演,按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 ",ans[i]); } return 0; }