• [ POI 2017 ] Podzielno


    (\)

    (Description)


    (B)进制数,每个数字(i(iin [0,B-1]))(A_i)个。用这些数字组成一个最大的(B)进制数(X)(不能有前导零,不需要
    用完所有数字),使得(X)(B-1)的倍数。(q)次询问,每次询问(X)(B)进制下的第(k)位数字是什么。

    • (Bin [2,10^6])(A_iin [1,10^6])(qin [1,10^5])(kin [1,10^{18}])

    (\)

    (Solution)


    • 首先考虑位本身的影响,因为(Bequiv1pmod{B-1}),则有(B^Kequiv1pmod{B-1}),所以位的不同不会影响数字对(B-1)的取模,换句话说,固定了选哪些数字之后,如何排列对取模后的答案没有影响。

    • 于是把每一位拆开看,假设一共有(len)个数位,第(i)位放的数为(d_i),则该数在(B-1)的剩余系下的答案为(egin{align}sum_{i=0}^{len-1}d_i imes B^iequiv sum_{i=0}^{len-1}d_ipmod{B-1}end{align})

    • 于是直接将给出的数字求和,并对(B-1)取模,注意到数据有一个很好的性质,所有的数字至少有一个,所以直接将求和取模得到的数个数(-1)即可,注意如果取模答案为(0)并不需要减掉个数。

    • 然后构造答案的方法显然,因为要组成的数字最大,所以大的数字放前面,这样询问即可在个数上二分了。

    (\)

    (Code)


    #include<cmath>
    #include<cstdio>
    #include<cctype>
    #include<cstdlib>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #define N 100010
    #define R register
    #define gc getchar
    using namespace std;
    
    int f[N];
    struct lim{int l,r;}s[N];
    struct seg{int l,r,val;}p[N];
    
    inline int rd(){
      int x=0; bool f=0; char c=gc();
      while(!isdigit(c)){if(c=='-')f=1;c=gc();}
      while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=gc();}
      return f?-x:x;
    }
    
    inline bool cmp1(lim x,lim y){return x.l==y.l?x.r<y.r:x.l<y.l;}
    
    inline bool cmp2(seg x,seg y){return x.r==y.r?x.l<y.l:x.r<y.r;}
    
    inline int find(int x){
      int l=0,r=x-1;
      while(l<r){
        int mid=((l+r+1)>>1);
        if(p[mid].r<p[x].l) l=mid;
        else r=mid-1;
      }
      return l;
    }
    
    int main(){
      int n=rd(),tot1=0,tot2=0;
      for(R int i=1,l,r;i<=n;++i){
        l=rd(); r=rd();
        if(l+r<n){s[++tot1].l=l+1;s[tot1].r=n-r;}
      }
      sort(s+1,s+1+tot1,cmp1);
      for(R int i=1,cnt;i<=tot1;++i){
        cnt=1;
        while(s[i+1].l==s[i].l&&s[i+1].r==s[i].r) ++cnt,++i;
        cnt=min(cnt,s[i].r-s[i].l+1);
        p[++tot2].l=s[i].l; p[tot2].r=s[i].r; p[tot2].val=cnt;
      }
      sort(p+1,p+1+tot2,cmp2);
      for(R int i=1;i<=tot2;++i)
        f[i]=max(f[i-1],f[find(i)]+p[i].val);
      printf("%d
    ",n-f[tot2]);
    
  • 相关阅读:
    Keras的安装与配置
    Hive实际应用小结
    SparkMLlib-----GMM算法
    ---------菜单目录---------
    Linux(Centos)下使用Docker安装 Portainer-ce(HTTPS支持,docker容器管理软件)
    Linux(Centos)下 docker-ce安装配置(TLS认证)、docker-compose安装与配置
    Centos8 安装进不了图形化安装界面,光标一直在闪解决方案
    开源镜像库
    vue模板项目 推荐项目 vue-element-admin
    Linux 服务器 网卡 流量统计 监控 (vnstat)最新版本安装使用
  • 原文地址:https://www.cnblogs.com/SGCollin/p/9609918.html
Copyright © 2020-2023  润新知