题目大意:

 有一张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\n" , 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 }

 

 posted on 2015-09-07 02:03  Love风吟  阅读(388)  评论(0编辑  收藏  举报