zoukankan      html  css  js  c++  java
  • 2017 Multi-University Training Contest

    链接:http://acm.hdu.edu.cn/showproblem.php?pid=6102

    题解:

    分析:有点难想。。首先逐个加入右端点,每加入一个,枚举倍数,和题解做法一样,然后更新每个Ai位置的值,当某个区间右端点恰好的刚刚枚举完的右端点时,这时候更新答案,对应询问的答案就是这个时候的区间和,用树状数组处理一下,可以先把询问按右端点从小到大排序,方便查找右端点恰好达到的区间。

    然后求互质个数的容斥,具体来说,首先预处理出1~1e5的数的因子和莫比乌斯函数,然后把右端点的倍数,从右往左扫,每加入一个新的,把它分解,然后查找它后面是某个因子倍数的数个数,容斥一下,再更新一下倍数的个数,更新一下该点的答案,继续往左扫,做完以后把个数清空,再做下一次的。可以做一个剪枝,直接把因子对应莫比乌斯函数为0的不放入预处理的数组中。

      1 #include<iostream>
      2 #include<cstdio>
      3 #include<cstring>
      4 #include<vector>
      5 #include<algorithm>
      6 using namespace std;
      7 typedef long long ll;
      8 const int maxn=1e5+5;
      9 int pri[maxn],len=0,mu[maxn];
     10 bool Is_pri[maxn];
     11 vector<int> factor[maxn];
     12 int n,m,a[maxn],l[maxn],r[maxn],order[maxn],loca[maxn];
     13 ll  ans[maxn];
     14 int temp[maxn],num[maxn],cnt=0;
     15 bool Cmp(int a,int b){return r[a]<r[b];}
     16 class TreeArray{
     17     ll c[maxn];
     18     int n;
     19 public:
     20     void init(int n){
     21         this->n=n;
     22         memset(c,0,sizeof(c));
     23     }
     24     void add(int k,ll num){
     25         while(k<=n){
     26             c[k]+=num;
     27             k+=k&-k;
     28         }
     29     }
     30     ll query(int k){
     31         ll sum=0;
     32         while(k){
     33             sum+=c[k];
     34             k-=k&-k;
     35         }
     36         return sum;
     37     }
     38     ll query(int l,int r){return query(r)-query(l-1);}
     39 }ta;
     40 void CalPri(){
     41     mu[1]=1;
     42     memset(Is_pri,-1,sizeof(Is_pri));
     43     for(int i=2;i<maxn;i++){
     44         if(Is_pri[i]){
     45             pri[len++]=i;
     46             mu[i]=-1;
     47         }
     48         for(int j=0;j<len&&pri[j]*i<maxn;j++){
     49             Is_pri[pri[j]*i]=false;
     50             mu[pri[j]*i]=-mu[i];
     51             if(i%pri[j]==0){
     52                 mu[pri[j]*i]=0;
     53                 break;
     54             }
     55         }
     56     }
     57 }
     58 void CalFactor(){
     59     for(int i=2;i<maxn;i++){
     60         for(int j=i;j<maxn;j+=i){
     61             if(mu[i])factor[j].push_back(i);
     62         }
     63     }
     64 }
     65 int main(){
     66 //    freopen("e:\in.txt","r",stdin);
     67     int T;
     68     CalPri();
     69     CalFactor();
     70     scanf("%d",&T);
     71     while(T--){
     72         scanf("%d%d",&n,&m);
     73         ta.init(n);
     74         for(int i=1;i<=n;i++){
     75             scanf("%d",&a[i]);
     76             loca[a[i]]=i;
     77         }
     78         for(int i=1;i<=m;i++){
     79             scanf("%d%d",&l[i],&r[i]);
     80             order[i]=i;
     81         }
     82         int idx=1;
     83         sort(order+1,order+m+1,Cmp);
     84         for(int i=3;i<=n;i++){
     85             while(idx<=m&&r[order[idx]]<i){
     86                 ans[order[idx]]=ta.query(l[order[idx]],r[order[idx]]);
     87                 idx++;
     88             }
     89             cnt=0;
     90             for(int k=2;k*a[i]<=n;k++){
     91                 if(loca[k*a[i]]<i)temp[cnt++]=loca[k*a[i]];
     92             }
     93             sort(temp,temp+cnt);
     94             for(int j=cnt-1;j>=0;j--){
     95                 int t=temp[j],s=a[t]/a[i];
     96                 ll sum=cnt-j-1;
     97                 for(int k=0;k<factor[s].size();k++){
     98                     int q=factor[s][k];
     99                     sum+=num[factor[s][k]]*mu[factor[s][k]];
    100                     num[factor[s][k]]++;
    101                 }
    102                 ta.add(t,sum*a[i]);
    103             }
    104             for(int j=cnt-1;j>=0;j--){
    105                 int t=temp[j],s=a[t]/a[i];
    106                 for(int k=0;k<factor[s].size();k++){
    107                     num[factor[s][k]]=0;
    108                 }
    109             }
    110         }
    111         while(idx<=m){
    112             ans[order[idx]]=ta.query(l[order[idx]],r[order[idx]]);
    113             idx++;
    114         }
    115         for(int i=1;i<=m;i++){
    116             printf("%lld
    ",ans[i]);
    117         }
    118     }
    119     return 0;
    120 }
  • 相关阅读:
    NodeJS系列~第一个小例子,实现了request.querystring功能
    JS~js里实现队列与堆栈
    最新CSS兼容方案
    js传真实地址 C:fakepath
    IE11的变化 navigator.userAgent中不再包含“MSIE”关键字
    看看该死的jquery.form.js的用法,不是个东西
    bootstrap模态框怎么传递参数
    方法的直接调用,反射调用
    IIS 7.5 配置伪静态
    TrippleDESCSPEncrypt 加密解密试试看
  • 原文地址:https://www.cnblogs.com/7391-KID/p/7362185.html
Copyright © 2011-2022 走看看