zoukankan      html  css  js  c++  java
  • [NOIP2019模拟赛]数数(gcd)

    题目大意:

      求l~r中有多少数与x互质,带单点修改

    分析:

      两个30的部分分很好打:

        ·n<=1000暴力O(nq)就好了

        ·$a_i<=100$用树状数组维护每个x的前缀和就好了

      100分做法有两种,一种是莫比乌斯反演(我不会),还有一种就是bitset乱搞

      我们先筛法筛出所有质数(大概不到10000个)然后对于每个质数建立一个bitset,表示对于第i个数在有第j个质数这个质因子

      求有多少数与x互质转换为有多少数与x不互质就好了

      对于每次询问把所有x的质因子找出来然后把这些数的bitset或起来再用类似前缀和的方法维护即可

      时间复杂度$O(frac{n*Q*logn}{32})$显然跑不满,所以卡一卡就过了(跑的比莫比乌斯反演快)

    代码:(这里把两种部分分的打法也都写上了)

      1 #pragma GCC optimize("Ofast")
      2 #include<bits/stdc++.h>
      3 #define lowbit(x) (x&(-x))
      4 using namespace std;
      5 inline int read(){
      6     int ans=0,f=1;char chr=getchar();
      7     while(!isdigit(chr)){if(chr=='-')f=-1;chr=getchar();}
      8     while(isdigit(chr)) {ans=(ans<<3)+(ans<<1)+chr-48;chr=getchar();}
      9     return ans*f;
     10 }const int M = 5e4+5;
     11 int n,m,a[M],Q,ans,gcd[101][101];
     12 struct P{
     13     int s[M];
     14     void Update(int x,int a){for(;x<=n;x+=lowbit(x)) s[x]+=a;}
     15     int Query(int x){int res=0;for(;x;x-=lowbit(x)) res+=s[x];return res;} 
     16 }t[101];
     17 //-------------------------------------------------第一个30pts --------------------------------------------------
     18 inline void Solve_1(){//n*Q<=1000000
     19     while(Q--){
     20         int opt=read(),x;
     21         if(opt==1)    x=read(),a[x]=read();
     22         else{
     23             int l=read(),r=read();
     24             x=read();ans=0;
     25             for(int i=l;i<=r;i++)
     26                 if(__gcd(x,a[i])==1)
     27                     ++ans;
     28             printf("%d
    ",ans);
     29         }
     30     }
     31 }
     32 //---------------------------------------第二个30pts ----------------------------------------------------- 
     33 inline void Solve_2(){//Ai<=100
     34     for(int i=1;i<=100;++i)
     35         for(int j=1;j<=100;++j)
     36             gcd[i][j]=__gcd(i,j);
     37     for(int i=1;i<=100;i++)
     38         for(int j=1;j<=n;j++)
     39             if(gcd[i][a[j]]==1)
     40                 t[i].Update(j,1);
     41     while(Q--){
     42         int opt=read();
     43         if(opt==1){
     44             int x=read(),y=read(),tt=a[x];
     45             a[x]=y;
     46             for(int i(1);i<=100;++i){
     47                 if(gcd[a[x]][i]!=1&&gcd[tt][i]==1)
     48                     t[i].Update(x,-1);
     49                 if(gcd[a[x]][i]==1&&gcd[tt][i]!=1)
     50                     t[i].Update(x,1);
     51             }
     52         }else{int l=read(),r=read(),x=read();
     53             printf("%d
    ",t[x].Query(r)-t[x].Query(l-1));
     54         }
     55     }
     56 }bitset<M>s[10000],now;
     57 int v[M*2],pri[M*2],tot;
     58 //----------------------------------------通解-------------------------------------------- 
     59 inline void Get_Pri(){
     60     for(int i=2;i<=100000;i++){
     61         if(!v[i]) v[i]=i,pri[++tot]=i;
     62         for(int j=1;j<=tot;j++){
     63             if(pri[j]>100000/i||pri[j]>v[i]) break;
     64             v[i*pri[j]]=pri[j];
     65         }
     66     }
     67 }
     68 inline void Update(int pos,int x,int y){
     69     int i=1;
     70     while(1){
     71         if(pri[i]*pri[i]>x) break;
     72         if(x%pri[i]==0){
     73             s[i][pos]=y;
     74             while(x%pri[i]==0) x/=pri[i];
     75         }i++;
     76     }if(x>1)s[lower_bound(pri+1,pri+tot+1,x)-pri][pos]=y;
     77 }
     78 inline void Solve(){
     79     Get_Pri();
     80     for(int i=1;i<=n;i++) Update(i,a[i],1);
     81     while(Q--){
     82         int opt=read();
     83         if(opt==1){
     84             int x=read(),y=read();
     85             Update(x,a[x],0),Update(x,y,1);
     86             a[x]=y;
     87         }else{
     88             int l=read(),r=read(),x=read();
     89             int i=1;now=0;
     90             while(1){
     91                 if(pri[i]*pri[i]>x) break;
     92                 if(x%pri[i]==0){
     93                     now|=s[i];
     94                     while(x%pri[i]==0) x/=pri[i];
     95                 }i++;
     96             }if(x>1) now|=s[lower_bound(pri+1,pri+tot+1,x)-pri];
     97             int Ans=r-l+1-(now>>l).count()+(now>>(r+1)).count();
     98             printf("%d
    ",Ans);
     99         }
    100     }
    101 }
    102 int main(){
    103     freopen("gcd.in","r",stdin);
    104     freopen("gcd.out","w",stdout);
    105     n=read();
    106     for(int i=1;i<=n;++i) a[i]=read();
    107     Q=read();
    108 //    if(n*Q<=1000000) Solve_1();
    109 //    else Solve_2();
    110     Solve();
    111     return 0;
    112 }
  • 相关阅读:
    js产生随机数
    Ajax库的编写及使用
    css水平竖直居中方式
    各大网站css初始化代码【转】
    文档对象模型-DOM(二)
    文档对象模型-DOM(一)
    nav标签使用说明
    html5学习整理-0311
    Python OpenCV —— Arithmetic
    关于python3 OpenCV的安装和配置
  • 原文地址:https://www.cnblogs.com/zhenglw/p/11337645.html
Copyright © 2011-2022 走看看