山东济南彤昌机械科技有限公司 山东济南江鹏工贸游有限公司

bzoj 3529 [Sdoi2014]数表(莫比乌斯反演+BIT)

 

Description

    有一张N×m的数表,其第i行第j列(1 < =i < =礼,1 < =j < =m)的数值为
能同时整除i和j的所有自然数之和。给定a,计算数表中不大于a的数之和。

Input

    输入包含多组数据。
    输入的第一行一个整数Q表示测试点内的数据组数,接下来Q行,每行三个整数n,m,a(|a| < =10^9)描述一组数据。

Output

    对每组数据,输出一行一个整数,表示答案模2^31的值。

Sample Input

2
4 4 3
10 10 5

Sample Output

20
148

HINT

 

1 < =N.m < =10^5  , 1 < =Q < =2×10^4

 

【思路】

 

  UPD:求a只和F(1..a)有关系改为:求a只和F(i)<=a的项有关系

  自然溢出,最后and 2^31-1

 

【代码】

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 using namespace std;
 5 
 6 const int N = 1e5+10;
 7 
 8 struct Node {
 9     int n,m,a,id;
10     bool operator< (const Node& rhs) const{
11         return a<rhs.a;
12     }
13 };
14 struct Fnode{
15     int num,id;
16     bool operator<(const Fnode& rhs) const{
17         return num<rhs.num;
18     }
19 };
20 
21 int mx,n,m,a;
22 int mu[N],su[N],sz,np[N],C[N],ans[N];
23 Node que[N]; Fnode F[N];
24 
25 void add(int x,int v)
26 {
27     for(;x<=mx;x+=x&-x) C[x]+=v;
28 }
29 int query(int x)
30 {
31     int res=0;
32     for(;x;x-=x&-x) res+=C[x];
33     return res;
34 }
35 
36 void get_mu()
37 {
38     int i,j;
39     mu[1]=1;
40     for(i=2;i<=mx;i++) {
41         if(!np[i])
42             mu[i]=-1,su[++sz]=i;
43         for(j=1;j<=sz&&i*su[j]<=mx;j++) {
44             np[i*su[j]]=1;
45             if(i%su[j]==0)
46                 mu[i*su[j]]=0;
47             else
48                 mu[i*su[j]]=-mu[i];
49         }
50     }
51 }
52 void get_F()
53 {
54     int i,j;
55     for(i=1;i<=mx;i++) {
56         for(j=i;j<=mx;j+=i)
57             F[j].num+=i;
58     }
59     for(i=1;i<=mx;i++) F[i].id=i;
60 }
61 
62 int main()
63 {
64     int T;
65     scanf("%d",&T);
66     for(int i=1;i<=T;i++) {
67         scanf("%d%d%d",&n,&m,&a);
68         if(n>m) swap(n,m);
69         que[i]=(Node){n,m,a,i};
70         mx=max(mx,n);
71     }
72     get_mu(); get_F();
73     sort(que+1,que+T+1);
74     sort(F+1,F+mx+1);
75     int now=0;
76     for(int i=1;i<=T;i++) {
77         while(now+1<=mx&&F[now+1].num<=que[i].a) {
78             now++;
79             for(int j=F[now].id;j<=mx;j+=F[now].id)
80                 add(j,F[now].num*mu[j/F[now].id]);
81         }
82         int id=que[i].id,last; n=que[i].n,m=que[i].m;
83         for(int j=1;j<=n;j=last+1) {
84             last=min(n/(n/j),m/(m/j));
85             ans[id]+=(query(last)-query(j-1))*(n/j)*(m/j);
86         }
87     }
88     for(int i=1;i<=T;i++)
89         printf("%d\n",ans[i]&0x7fffffff);
90     return 0;
91 }

 

posted on 2016-03-07 11:59  hahalidaxin  阅读(363)  评论(0编辑  收藏  举报