zoukankan      html  css  js  c++  java
  • bzoj 3529 数表 莫比乌斯反演+树状数组

     题目大意:

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

    http://wenku.baidu.com/link?url=1zHluup-GXHdByoQXhMRwRu22Uu15y4DztIr1_hKVxjHJmuLQF4_01UQhLEOR7RJIpsGyfD_5fXrx9DE7sY6JeukaNUY83In097GjUOmZ7K

    ppt课件中讲的很仔细了

      1 #include <bits/stdc++.h>
      2 
      3 using namespace std;
      4 #define N 100000
      5 #define ll long long
      6 #define lowbit(x) x&(-x)
      7 typedef pair<int , int> pii;
      8 int sum[N+5] , mu[N+5] , prime[N+5] , tot;
      9 bool check[N+5];
     10 pii f[N+5];
     11 
     12 void get_mu()
     13 {
     14     mu[1] = 1;
     15     for(int i=1 ; i<=N ; i++) f[i].first=1 , f[i].second = i;
     16     for(int i=2 ; i<=N ; i++){
     17         if(!check[i]){
     18             mu[i] = -1;
     19             prime[tot++] = i;
     20         }
     21         for(int j=0 ; j<tot ; j++){
     22             if((ll)prime[j]*i>N) break;
     23             check[i*prime[j]] = true;
     24             if(i%prime[j]){
     25                 mu[i*prime[j]] = -mu[i];
     26             }else break;
     27         }
     28     }
     29     for(int i=2 ; i<=N ; i++)
     30         for(int j=i ; j<=N ; j+=i)
     31             f[j].first += i;
     32 }
     33 
     34 struct Query{
     35     int n , m , a , id;
     36     void in(int i){scanf("%d%d%d" , &n , &m , &a) ; id=i;}
     37     void reset(){if(n>m) swap(n,m);}
     38     bool operator<(const Query &m)const {
     39         return a<m.a;
     40     }
     41 }qu[N];
     42 
     43 int mxl , Q , ans[N];
     44 
     45 void add(int x , int v)
     46 {
     47     for(int i=x ; i<=mxl ; i+=lowbit(i)) sum[i]+=v;
     48 }
     49 
     50 int query(int x)
     51 {
     52     int ret = 0;
     53     for(int i=x ; i>0 ; i-=lowbit(i)) ret += sum[i];
     54     return ret;
     55 }
     56 
     57 int find(int n , int m)
     58 {
     59     int ret = 0 , last;
     60     for(int i=1 ; i<=n ; i=last+1){
     61         last = min(n/(n/i) , m/(m/i));
     62         ret += n/i*(m/i)*(query(last)-query(i-1));
     63       //  cout<<n<<" "<<m<<" "<<ret<<" "<<query(last)<<" "<<query(i-1)<<endl;
     64     }
     65     return ret&(0x7fffffff);
     66 }
     67 
     68 void solve()
     69 {
     70     memset(sum , 0 , sizeof(sum));
     71     int index = 1 , cnt=0;
     72     for(int i=1 ; i<=Q ; i++){
     73         while(f[index].first<=qu[i].a&&cnt<mxl){
     74             for(int j=f[index].second , k=1 ; j<=mxl ; j+=f[index].second ,k++){
     75                // cout<<index<<" "<<f[index].second<< " "<<f[index].first<<" "<<k<<" "<<mu[k]<<endl;
     76                 add(j , f[index].first*mu[k]);
     77             }
     78             index++;
     79             if(f[index].second<=mxl) cnt++;
     80         }
     81         ans[qu[i].id] = find(qu[i].n , qu[i].m);
     82     }
     83     for(int i=1 ; i<=Q ; i++) printf("%d
    " , ans[i]);
     84 }
     85 
     86 int main()
     87 {
     88     //freopen("in.txt" , "r" , stdin);
     89     get_mu();
     90     sort(f+1 , f+N+1);
     91     while(~scanf("%d" , &Q)){
     92         mxl = 0;
     93         for(int i=1 ; i<=Q ; i++) {
     94             qu[i].in(i) , qu[i].reset();
     95             mxl = max(mxl , qu[i].n);
     96         }
     97         sort(qu+1 , qu+Q+1);
     98         solve();
     99     }
    100     return 0;
    101 }
  • 相关阅读:
    2019 学霸君java面试笔试题 (含面试题解析)
    2019 大众书网Java面试笔试题 (含面试题解析)
    2019 中细软java面试笔试题 (含面试题解析)
    2019 企叮咚java面试笔试题 (含面试题解析)
    js 去掉数组对象中的重复对象
    canvas霓虹雨
    nvm的安装
    socket.io 中文文档
    Nginx(三)------nginx 反向代理
    github入门到上传本地项目
  • 原文地址:https://www.cnblogs.com/CSU3901130321/p/4787828.html
Copyright © 2011-2022 走看看