BZOJ 3529[SDOI2014]数表

题面:

3529: [Sdoi2014]数表

Time Limit: 10 Sec  Memory Limit: 512 MB
Submit: 1908  Solved: 969
[Submit][Status][Discuss]

Description

    有一张N×m的数表,其第i行第j列(1 < =i < =n,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

题目要求 

$\sum_{i=1}^{n}\sum_{j=1}^{m}\sigma(gcd(i,j))$

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

$=\sum_{T=1}\lfloor\frac{n}{T}\rfloor\lfloor\frac{m}{T}\rfloor\sum_{d|T}\mu(\frac{T}{d})\sigma(d)$

令$g[T]=\sum_{d|T}\mu(\frac{T}{d})\sigma(d)$

法一:

线性筛求出$g[T]$,$O(n)$。

法二:

枚举$d$,更新$d$倍数的$g$,$O(nlogn)$。

但是有$a$的限制,只能用法二。

将$\sigma(i)$由小到大排序,将询问按$a$由小到大排序,离线回答询问。

每次将小于等于$a_{i}$的$f[T]$加入树状数组,分块回答询问。

时间复杂度$O(nlog^{2}n+T\sqrt nlogn)$。

  1 #include<iostream>
  2 #include<stdio.h>
  3 #include<algorithm>
  4 using namespace std;
  5 #define maxn 100000
  6 #define lowbit(x) x&(-x)
  7 #define INF 2147483647
  8 struct node
  9 {
 10     int x;int y;
 11 }id[maxn+1];
 12 bool cmp(const node &a,const node &b)
 13 {
 14     return a.x<b.x;
 15 }
 16 int p[maxn+1];
 17 int cnt,mu[maxn+1];
 18 bool book[maxn+1];
 19 void init()
 20 {
 21     mu[1]=1;
 22     id[1]=(node){1,1};
 23     for(int i=2;i<=maxn;i++)
 24     {
 25         if(!book[i])
 26         {
 27             p[++cnt]=i;
 28             id[i]=(node){i+1,i};
 29             mu[i]=-1;
 30         }
 31         for(int j=1;j<=cnt&&i*p[j]<=maxn;j++)
 32         {
 33             book[i*p[j]]=true;
 34             if(i%p[j]!=0)
 35             {
 36                 mu[i*p[j]]=-mu[i];
 37                 id[i*p[j]]=(node){id[i].x*id[p[j]].x,i*p[j]};
 38             }
 39             else
 40             {
 41                 id[i*p[j]]=(node){id[i].x+(id[i].x-id[i/p[j]].x)*p[j],i*p[j]};
 42                 break;
 43             }
 44         }
 45     }
 46 }
 47 int T;
 48 struct QAQ
 49 {
 50     int n,m,w,dfn;
 51 }QWQ[20002];
 52 bool cmp1(const QAQ&a,const QAQ&b)
 53 {
 54     return a.w<b.w;
 55 }
 56 #define maxm 404000
 57 int c[maxm+1],ans[20002];
 58 void update(int x,int w)
 59 {
 60     for(;x<=maxm;x+=lowbit(x))
 61         c[x]+=w;
 62 }
 63 int query(int x)
 64 {
 65     int ans=0;
 66     for(;x>0;x-=lowbit(x))
 67         ans+=c[x];
 68     return ans;
 69 }
 70 int qaq(int n,int m)
 71 {
 72     int last=0;
 73     int sum=0;
 74     if(n>m)
 75         swap(n,m);
 76     for(int i=1;i<=n;i=last+1)
 77     {
 78         last=min(n/(n/i),m/(m/i));
 79         sum+=(n/i)*(m/i)*(query(last)-query(i-1));
 80     }
 81     return sum;
 82 }
 83 void pushup(int i)
 84 {
 85     for(int j=1;id[i].y*j<=maxm;j++)
 86         update(j*id[i].y,id[i].x*mu[j]);
 87 }
 88 void work()
 89 {
 90     int tmp=0;
 91     for(int i=1;i<=T;i++)
 92     {
 93         while(tmp+1<=maxn&&id[tmp+1].x<=QWQ[i].w)
 94             pushup(++tmp);
 95         ans[QWQ[i].dfn]=qaq(QWQ[i].n,QWQ[i].m);
 96     }
 97 }
 98 int main()
 99 {
100     init();
101     scanf("%d",&T);
102     for(int i=1;i<=T;i++)
103     {
104         scanf("%d%d%d",&QWQ[i].n,&QWQ[i].m,&QWQ[i].w);
105         QWQ[i].dfn=i;
106     }
107     sort(id+1,id+maxn+1,cmp);
108     sort(QWQ+1,QWQ+T+1,cmp1);
109     work();
110     for(int i=1;i<=T;i++)
111         printf("%d\n",(ans[i]&INF));
112 } 
BZOJ 3529

 

posted @ 2017-07-15 17:34  avancent  阅读(165)  评论(0编辑  收藏  举报