[bzoj3529]数表

记f(n)表示n的约数和,先不考虑a的限制,那么即求$\sum_{i=1}^{n}\sum_{j=1}^{m}f(gcd(i,j))$
枚举$d=gcd(i,j)$,即$\sum_{d=1}^{n}f(d)\sum_{g|d}(n/gd)(m/gd)\mu(g)$(后面就是指公约数为d的数对个数)
令$t=gd$,即$\sum_{t=1}^{n}(n/t)(m/t)\sum_{d|t}f(d)\cdot \mu(t/d)$,对后半部分预处理(先线性筛出f和$\mu$,然后$o(nln(n))$求)+前半部分数论分块即可快速求出
离线,将询问按照a排序,然后不断插入f(i)(即修改所有是i约数的t位置,暴力),用树状数组来支持数论分块即可

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define N 100005
 4 #define L (k<<1)
 5 #define R (L+1)
 6 #define mid (l+r>>1)
 7 #define ui unsigned int
 8 struct ji{
 9     int n,m,a,id;
10     bool operator < (const ji &k)const{
11         return a<k.a;
12     }
13 }q[N];
14 int t,n,m,a,vis[N],p[N],mu[N],id[N];
15 ui f[N],ans[N],tr[N<<2];
16 bool cmp(int x,int y){
17     return f[x]<f[y];
18 }
19 void update(int k,int l,int r,int x,int y){
20     if (l==r){
21         tr[k]+=y;
22         return;
23     }
24     if (x<=mid)update(L,l,mid,x,y);
25     else update(R,mid+1,r,x,y);
26     tr[k]=tr[L]+tr[R];
27 }
28 ui query(int k,int l,int r,int x,int y){
29     if ((l>y)||(x>r))return 0;
30     if ((x<=l)&&(r<=y))return tr[k];
31     return query(L,l,mid,x,y)+query(R,mid+1,r,x,y);
32 }
33 int main(){
34     mu[1]=f[1]=1;
35     for(int i=2;i<N-4;i++){
36         if (!vis[i]){
37             p[++p[0]]=i;
38             mu[i]=-1;
39             f[i]=i+1;
40         }
41         for(int j=1;(j<=p[0])&&(i*p[j]<N-4);j++){
42             vis[i*p[j]]=1;
43             for(int k=i;;k/=p[j])
44                 if (k%p[j]){
45                     if (k>1)f[i*p[j]]=f[k]*f[i*p[j]/k];
46                     else f[i*p[j]]=f[i]+i*p[j];
47                     break;
48                 }
49             if (i%p[j]==0)break;
50             mu[i*p[j]]=-mu[i];
51         }
52     }
53     for(int i=1;i<N-4;i++)id[i]=i;
54     sort(id+1,id+N-4,cmp);
55     scanf("%d",&t);
56     for(int i=1;i<=t;i++){
57         scanf("%d%d%d",&n,&m,&a);
58         if (n>m)swap(n,m); 
59         q[i]=ji{n,m,a,i};
60     }
61     sort(q+1,q+t+1);
62     for(int i=1,j=1;i<=t;i++){
63         for(;(j<N-4)&&(f[id[j]]<=q[i].a);j++)
64             for(int k=1;k<=(N-5)/id[j];k++)update(1,1,N-5,k*id[j],f[id[j]]*mu[k]);
65         for(int l=1,r;l<=q[i].n;l=r+1){
66             r=min(q[i].n/(q[i].n/l),q[i].m/(q[i].m/l));
67             ans[q[i].id]+=(q[i].n/l)*(q[i].m/l)*query(1,1,N-5,l,r);
68         }
69     }
70     for(int i=1;i<=t;i++)printf("%u\n",ans[i]&2147483647);
71 }
View Code

 

posted @ 2019-10-24 18:06  PYWBKTDA  阅读(112)  评论(0编辑  收藏  举报