这题并没有做出来。。
设
f(i)=∑d|id
,考虑按f(i)排序,则对于询问
(n,m),(n≤m)
,f(i)会贡献
∑⌊nd⌋d=1μ(d)⌊nid⌋⌊mid⌋
,这样我们按照id考虑即可。。
但是我做的时候错误地把它化成了这样:
∑⌊nd⌋d=1μ(d)⌊⌊ni⌋d⌋⌊⌊mi⌋d⌋
这样就很难考虑出来该怎么做了。。
代码:
#include<cstdio>
#include<iostream>
using namespace std;
#include<algorithm>
struct QS{
int n,m,a,i;
bool operator < (const QS & o)const{
return a<o.a;
}
}q[20005];
int ans[20005];
int bit[100005];
const int S=400;
int f[405];
int N;
void update(int x,int delta){
for(;x<=N;x+=x&-x)bit[x]+=delta;
}
int query(int x){
int ans=0;
for(;x;x-=x&-x)ans+=bit[x];
return ans;
}
int mu[100005],prime[10005],smp[100005];
pair<int,int> d[100005];
int main(){
freopen("bzoj_3529.in","r",stdin);
//freopen("bzoj_3529.out","w",stdout);
int Q,i;
scanf("%d",&Q);
for(i=Q;i--;){
scanf("%d%d%d",&q[i].n,&q[i].m,&q[i].a);
if(q[i].n>q[i].m)swap(q[i].n,q[i].m);
N=max(N,q[i].m);
q[i].i=i;
}
sort(q,q+Q);
int j;
mu[1]=smp[1]=1;
d[1]=make_pair(1,1);
for(i=2;i<=N;++i){
d[i].second=i;
if(smp[i]==0){
prime[++prime[0]]=i;
d[i].first=smp[i]=i+1;
mu[i]=-1;
}
for(j=1;j<=prime[0]&&i*prime[j]<=N;++j)
if(i%prime[j]){
mu[i*prime[j]]=-mu[i];
smp[i*prime[j]]=prime[j]+1;
d[i*prime[j]].first=d[i].first*smp[i*prime[j]];
//printf("%d(%d)*%d->%d(%d)\n",d[i],i,prime[j]+1,d[i*prime[j]],i*prime[j]);
}
else{
smp[i*prime[j]]=smp[i]*prime[j]+1;
d[i*prime[j]].first=d[i].first/smp[i]*smp[i*prime[j]];
//printf("%d(%d)/%d*%d->%d(%d)\n",d[i],i,smp[i],smp[i*prime[j]],d[i*prime[j]],i*prime[j]);
}
}
//for(i=1;i<=10;++i)printf("%d:%d %d\n",i,d[i],smp[i]);
sort(d+1,d+N+1);
int k,o=0;
q[Q].a=0x7fffffff,d[N+1].first=0x7fffffff;
for(i=1;i<=N;){
do{
for(j=d[i].second,k=1;j<=min(S,N);++k,j+=d[i].second)
if(mu[k]){
//cout<<"update:"<<j<<endl;
f[j]+=mu[k]*d[i].first;
}
for(;j<=N;++k,j+=d[i].second)
if(mu[k])
update(j,mu[k]*d[i].first);
//cout<<"Add:"<<d[i].first<<","<<d[i].second<<endl;
++i;
}while(d[i].first==d[i-1].first);
for(;q[o].a<d[i].first;++o){
for(j=1;j<=min(S,q[o].n);++j){
//cout<<"Q["<<j<<"]:"<<f[j]<<"\n";
ans[q[o].i]+=(q[o].n/j)*(q[o].m/j)*f[j];
}
for(;j<=q[o].n;j=k+1){
k=min(q[o].n/(q[o].n/j),q[o].m/(q[o].m/j));
//cout<<"Q["<<j<<","<<k<<"]\n";
ans[q[o].i]+=(q[o].n/j)*(q[o].m/j)*(query(k)-query(j-1));
}
}
}
for(i=Q;i--;)printf("%d\n",ans[i]&0x7fffffff);
}
总结:一定要注意[[n/a]/b]=[n/ab]。