BZOJ 3529 数表(莫比乌斯反演)

http://www.lydsy.com/JudgeOnline/problem.php?id=3529

思路:令F(i)为i的约数和,

1<=x<=n,1<=y<=m

G(i)为i|gcd(x,y)的个数

g(i)为i=gcd(x,y)的个数

G(i)=floor(n/i)*floor(m/i)

g(i)=Σu(d/i)*G(d) (i|d)

F(i)可以用线性筛O(n)处理

ans=(1<=i<=min(n,m)) Σg(i)*F(i)=Σ F(i)*ΣG(d)*u(d/i) (i|d)

=(1<=d<=min(n,m)) ΣG(d)* Σ(i|d) u(d/i)*F(i)

 1 #include<algorithm>
 2 #include<cstdio>
 3 #include<cmath>
 4 #include<cstring>
 5 #include<iostream>
 6 #define ll long long
 7 #define inf 0x7fffffff
 8 std::pair<int,int>f[200005];
 9 struct node{
10     int n,m,id,a;
11 }q[200005];
12 int mx,v[200005],p[200005],mark[200005],mul[200005],ans[200005];
13 int lowbit(int x){
14     return x&(-x);
15 }
16 int read(){
17     char ch=getchar();int t=0,f=1;
18     while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();}
19     while ('0'<=ch&&ch<='9'){t=t*10+ch-'0';ch=getchar();}
20     return t*f;
21 }
22 int Read(){
23     char ch=getchar();ll t=0,f=1;
24     while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();}
25     while ('0'<=ch&&ch<='9'){t=t*10+ch-'0';ch=getchar();}
26     return t*f;
27 }
28 bool cmp(node a,node b){
29     return a.a<b.a;
30 }
31 void add(int x,int y){
32     for (int i=x;i<=mx;i+=lowbit(i)){
33         v[i]+=y;
34     }
35 }
36 int query(int x){
37     int res=0;
38     if (x==0) return 0;
39     for (int i=x;i;i-=lowbit(i)){
40         res+=v[i];
41     }
42     return res;
43 }
44 void init(){
45     mul[1]=1;
46     for (int i=2;i<=mx;i++){
47         if (!mark[i]) {
48             p[++p[0]]=i;
49             mul[i]=-1;
50         }
51         for (int j=1;j<=p[0]&&i*p[j]<=mx;j++){
52             mark[i*p[j]]=1;
53             if (i%p[j]) mul[i*p[j]]=mul[i]*(-1);
54             else {
55                 mul[i*p[j]]=0;
56                 break;
57             }
58         }
59     }
60     for (int i=1;i<=mx;i++)
61      for (int j=i;j<=mx;j+=i)
62       f[j].first+=i;
63     for (int i=1;i<=mx;i++) f[i].second=i;  
64 }
65 void solve(int k){
66     int id=q[k].id,n=q[k].n,m=q[k].m;
67     for (int i=1,j;i<=q[k].n;i=j+1){
68         j=std::min(n/(n/i),m/(m/i));
69         ans[id]+=(n/i)*(m/i)*(query(j)-query(i-1));
70     }
71 }
72 int main(){
73     int Q=read();
74     for (int i=1;i<=Q;i++){
75         q[i].n=read(),q[i].m=read(),q[i].a=read();q[i].id=i;
76         if (q[i].n>q[i].m) std::swap(q[i].n,q[i].m);
77         mx=std::max(mx,q[i].n);
78     }
79     init();
80     std::sort(q+1,q+1+Q,cmp);
81     std::sort(f+1,f+1+mx);
82     int now=0;
83     for (int i=1;i<=Q;i++){
84         while (now+1<=mx&&f[now+1].first<=q[i].a){
85             now++;
86             for (int j=f[now].second;j<=mx;j+=f[now].second){
87                 add(j,f[now].first*mul[j/f[now].second]);
88             }
89         }
90         solve(i);
91     }
92     for (int i=1;i<=Q;i++)
93      printf("%d\n",ans[i]&inf);
94 }

 

posted @ 2016-06-14 10:06  GFY  阅读(212)  评论(0编辑  收藏  举报