# BZOJ3529: [Sdoi2014]数表

BZOJ3529: [Sdoi2014]数表

## Input

1 < =N．m < =10^5  ， 1 < =Q < =2×10^4

2
4 4 3
10 10 5

## Sample Output

20
148

$$Ans=\sum_{d=1}^n\sum_{i=1}^n\sum_{j=1}^mf(d)[gcd(i,j)==d]$$

$$Ans=\sum_{d=1}^nf(d)\sum_{i=1}^n\sum_{j=1}^m[gcd(i,j)==d]$$

$$Ans=\sum_{d=1}^nf(d)\sum_{i=1}^{\lfloor\frac{n}{d}\rfloor}\mu(i)\lfloor\frac{n}{id}\rfloor\lfloor\frac{m}{id}\rfloor$$

$$Ans=\sum_{D=1}^n\sum_{d|D}f(d)\mu(\frac{D}{d})\lfloor\frac{n}{D}\rfloor\lfloor\frac{m}{D}\rfloor$$

$$Ans=\sum_{D=1}^n\lfloor\frac{n}{D}\rfloor\lfloor\frac{m}{D}\rfloor\sum_{d|D}f(d)\mu(\frac{D}{d})$$

$$\frac{n}{1}+\frac{n}{2}+\frac{n}{3}+...+\frac{n}{n}=nlog_2n$$

#include<iostream>
#include<algorithm>
#include<cstdio>
#define MAXN 100010
using namespace std;
int n=0,q;
int bit[MAXN],ans[MAXN];
int k=0,prime[MAXN],mu[MAXN],sum[MAXN],pos[MAXN];
bool np[MAXN];
struct Question{
int n,m,a,id;
}que[MAXN];
int date=0,w=1;char c=0;
while(c<'0'||c>'9'){if(c=='-')w=-1;c=getchar();}
while(c>='0'&&c<='9'){date=date*10+c-'0';c=getchar();}
return date*w;
}
inline bool cmp1(const int &p,const int &q){
return sum[p]<sum[q];
}
inline bool cmp2(const Question &p,const Question &q){
return p.a<q.a;
}
inline int lowbit(int x){return x&(-x);}
inline void update(int x,int v){for(;x<=n;x+=lowbit(x))bit[x]+=v;}
inline int query(int x){int s=0;for(;x;x-=lowbit(x))s+=bit[x];return s;}
void make(){
int m=n;
mu[1]=1;
for(int i=2;i<=m;i++){
if(!np[i]){
prime[++k]=i;
mu[i]=-1;
}
for(int j=1;j<=k&&prime[j]*i<=m;j++){
np[prime[j]*i]=true;
if(i%prime[j]==0)break;
mu[prime[j]*i]=-mu[i];
}
}
for(int i=1;i<=m;i++){
pos[i]=i;
for(int j=i;j<=m;j+=i)sum[j]+=i;
}
sort(pos+1,pos+m+1,cmp1);
}
int solve(int n,int m){
int ans=0;
for(int i=1,last=1;i<=n;i=last+1){
last=min(n/(n/i),m/(m/i));
ans+=(n/i)*(m/i)*(query(last)-query(i-1));
}
return ans;
}
void work(){
for(int i=1,now=1;i<=q;i++){
for(;sum[pos[now]]<=que[i].a&&now<=n;now++)
for(int k=pos[now];k<=n;k+=pos[now])
update(k,sum[pos[now]]*mu[k/pos[now]]);
ans[que[i].id]=solve(que[i].n,que[i].m);
}
for(int i=1;i<=q;i++)printf("%d\n",ans[i]&2147483647);
}
void init(){
for(int i=1;i<=q;i++){
if(que[i].n>que[i].m)swap(que[i].n,que[i].m);
que[i].a=max(0,que[i].a);
que[i].id=i;
n=max(n,que[i].m);
}
sort(que+1,que+q+1,cmp2);
}
int main(){
init();
make();
work();
return 0;
}


posted @ 2018-08-10 17:59  符拉迪沃斯托克  阅读(164)  评论(0编辑  收藏  举报
Live2D