zoukankan      html  css  js  c++  java
  • 【SPOJ 2319】 BIGSEQ

    BIGSEQ - Sequence

    You are given the sequence of all K-digit binary numbers: 0, 1,..., 2K-1. You need to fully partition the sequence into M chunks. Each chunk must be a consecutive subsequence of the original sequence. Let Si (1 ≤ i ≤ M) be the total number of 1's in all numbers in the ith chunk when written in binary, and let S be the maximum of all Si, i.e. the maximum number of 1's in any chunk. Your goal is to minimize S.

    Input

    In the first line of input, two numbers, K and M (1 ≤ K ≤ 100, 1 ≤ M ≤ 100, M ≤ 2^K), are given, separated by a single space character.

    Output

    In one line of the output, write the minimum S that can be obtained by some split. Write it without leading zeros. The result is not guaranteed to fit in a 64-bit integer.

    Example

    Input:
    3 4
    
    Output:
    4
     
    【题意】
      给定所有 K 位二进制数:0,1,…,2^K-1。你需要将它们分成恰好 M 组,每组都是原序列中连续的一些数。设 Si(1 ≤ i ≤ M)表示第 i 组中所有数的二进制表示中 1 的个数,S 等于所有 Si 中的最大值。你的任务是令 S 最小。

    【分析】
      这题竟然1A了超级感动。
      人生第一道重载运算符的高精度。
      主要就是高精度真是好恶心哦..看着别人的代码打的,重载运算符之后就直接用了很方便。
      
       进入正题,最大值最小,我们就想到可以二分S,然后划分区间使得每个区间都小于S。
      问题就变成了有限制S,然后把它划分成最少的区间,判断区间数是否<=m。
      假设我们现在在st的位置,要找最远的ed使得st+1到ed中的数的1的个数<=S。
      设c[i]表示小于等于i的数的1的个数和,上面的限制就是c[ed]-c[st]<=S -> c[ed]<=S+c[st]
      所以变成找最大的ed使
    c[ed]<=S+c[st]。
      c数组当然不能每个都求,我们用到他的时候就用数位DP求,具体过程就是模拟填数。
      
    找最大的ed使c[ed]<=S+c[st]也是一个模拟填数的过程,也是一个数位DP。
     
      数位DP中用到的数组是d[i],f[i]。
    d[i]表示2^i,f[i]表示小于等于d[i]的数中的1的个数和。初始化求出这两个数组。
      
      填数的时候注意1的个数计算。我一开始就傻逼了。
      前面填过的1并没有在答案中减去,判断可不可以走左子树的时候要记得把这个也加上判断。

    代码如下:
      1 #include<cstdio>
      2 #include<cstdlib>
      3 #include<cstring>
      4 #include<iostream>
      5 #include<algorithm>
      6 #include<string>
      7 #include<queue>
      8 #include<cmath>
      9 using namespace std;
     10 #define Maxn 110
     11 
     12 struct bign
     13 {
     14     int len,a[Maxn];
     15     bign ()
     16     {
     17         memset(a,0,sizeof(a));
     18         len=1;
     19     }
     20     bign (int num)
     21     {
     22         *this = num;
     23     }
     24     bign operator = (const int num)
     25     {
     26         char s[Maxn];
     27         sprintf(s,"%d",num);
     28         *this = s;
     29         return *this;
     30     }
     31     bign operator = (const char *num)
     32     {
     33         while(num[0]=='0') num++;
     34         len=strlen(num);
     35         for(int i=0;i<len;i++)
     36           a[i]=num[len-i-1]-'0';
     37         return *this;
     38     }
     39     bign operator + (const bign &b)
     40     {
     41         bign c;
     42         c.len=0;
     43         for(int i=0,g=0;g||i<max(len,b.len);i++)
     44         {
     45             int x=g;
     46             if(i<len) x+=a[i];
     47             if(i<b.len) x+=b.a[i];
     48             c.a[c.len++]=x%10;
     49             g=x/10;
     50         }
     51         return c;
     52     }
     53     bign operator += (const bign &b)
     54     {
     55         *this=*this+b;
     56         return *this;
     57     }
     58     void clean()
     59     {
     60         while(len>1 && !a[len-1]) len--;
     61     }
     62     bign operator * (const bign &b)
     63     {
     64         bign c;
     65         c.len=len+b.len;
     66         for(int i=0;i<len;i++)
     67          for(int j=0;j<b.len;j++)
     68             c.a[i+j]+=a[i]*b.a[j];
     69         for(int i=0;i<c.len;i++)
     70         {
     71             c.a[i+1]+=c.a[i]/10;
     72             c.a[i]%=10;
     73         }
     74         c.clean();
     75         return c;
     76     }
     77     bign operator *= (const bign &b)
     78     {
     79         *this=*this * b;
     80         return *this;
     81     }
     82     bign operator - (const bign b)
     83     {
     84         bign c;
     85         c.len=0;
     86         for(int i=0,g=0;i<len;i++)
     87         {
     88             int x=a[i]-g;
     89             if(i<b.len) x-=b.a[i];
     90             if(x>=0) g=0;
     91             else
     92             {
     93                 g=1;
     94                 x+=10;
     95             }
     96             c.a[c.len++]=x;
     97         }
     98         c.clean();
     99         return c;
    100     }
    101     bign operator -= (const bign &b)
    102     {
    103         *this = *this -b;
    104         return *this;
    105     }
    106     bign operator / (const int b)
    107     {
    108         bign c;
    109         int f=0;
    110         for(int i=len-1;i>=0;i--)
    111         {
    112             f=f*10+a[i];
    113             c.a[i]=f/b;
    114             f=f%b;
    115         }
    116         c.len=len;
    117         c.clean();
    118         return c;
    119     }
    120     bign operator / (const bign &b)
    121     {
    122         bign c,f=0;
    123         for(int i=len-1;i>=0;i--)
    124         {
    125             f=f*10;
    126             f.a[0]=a[i];
    127             while(f>=b)
    128             {
    129                 f-=b;
    130                 c.a[i]++;
    131             }
    132         }
    133         c.len=len;
    134         c.clean();
    135         return c;
    136     }
    137     bign operator /= (const bign &b)
    138     {
    139         *this = * this /b;
    140         return * this;
    141     }
    142     bign operator % (const bign &b)
    143     {
    144         bign r= *this /b;
    145         r=*this-r*b;
    146         return r;
    147     }
    148     bign operator %= (const bign &b)
    149     {
    150         *this=*this%b;
    151         return *this;
    152     }
    153     bool operator < (const bign &b)
    154     {
    155         if(len!=b.len) return len<b.len;
    156         for(int i=len-1;i>=0;i--)
    157          if(a[i]!=b.a[i]) return a[i]<b.a[i];
    158         return false;
    159     }
    160     bool operator > (const bign &b)
    161     {
    162         if(len!=b.len) return len>b.len;
    163         for(int i=len-1;i>=0;i--)
    164          if(a[i]!=b.a[i]) return a[i]>b.a[i];
    165         return false;
    166     }
    167     bool operator == (const bign &b)
    168     {
    169         return !(*this>b) && !(*this<b);
    170     }
    171     bool operator != (const bign &b)
    172     {
    173         return !(*this==b);
    174     }
    175     bool operator <= (const bign &b)
    176     {
    177         return (*this<b)||(*this==b);
    178     }
    179     bool operator >= (const bign &b)
    180     {
    181         return (*this>b)||(*this==b);
    182     }
    183 };
    184 
    185 void output(bign x)
    186 {
    187     for(int i=x.len-1;i>=0;i--) printf("%c",x.a[i]+'0');
    188     printf("
    ");
    189 }
    190 
    191 int k,m;
    192 bign d[Maxn],f[Maxn];
    193 void init()
    194 {
    195     d[0]=1;
    196     for(int i=1;i<=k;i++) d[i]=d[i-1]*2;
    197     f[1]=1;
    198     for(int i=1;i<=k;i++) f[i]=f[i-1]*2+d[i-1];
    199 }
    200 
    201 bign get_ct(bign x)
    202 {
    203     bign ans=0;
    204     if(x==-1) return 0;
    205     int y=0;
    206     for(int i=k;i>=1;i--)
    207     {
    208         bign now=x/d[i-1];
    209         if(now==1) ans+=f[i-1]+d[i-1]*y,y++;
    210         x%=d[i-1];
    211     }
    212     return ans+y;
    213 }
    214 
    215 bign get_f(bign x)
    216 {
    217     bign ans=0;
    218     int y=0;
    219     for(int i=k;i>=1;i--)
    220     {
    221         if(d[i-1]*y+f[i-1]<x) ans+=d[i-1],x-=d[i-1]*y+f[i-1],y++;
    222     }
    223     if(x>=y) return ans; 
    224     return ans-1;
    225 }
    226 
    227 bool check(bign x)
    228 {
    229     bign st=0;
    230     int now=0;
    231     while(st<d[k]-1)
    232     {
    233         bign y=get_ct(st),ed=get_f(y+x);
    234         now++;
    235         if(now>m) return 0;
    236         st=ed;
    237     }
    238     return 1;
    239 }
    240 
    241 void ffind()
    242 {
    243     bign l=1,r=f[k];
    244     while(l<r)
    245     {
    246         bign mid=(l+r)/2;
    247         if(check(mid)) r=mid;
    248         else l=mid+1;
    249     }
    250     output(l);
    251 }
    252 
    253 int main()
    254 {
    255     scanf("%d%d",&k,&m);
    256     init();
    257     ffind();
    258     return 0;
    259 }
    [SPOJ 2319]
    
    
    
     
    
    

    打这个真是太不容易了!!!!


    放一个大神的题解,如果看不懂我说的东西的话:

     
    
    
  • 相关阅读:
    二叉树的遍历以及创建——by leona
    利用图像压缩模型抵御对抗样本 by ch
    卡尔曼滤波器及其扩展的个人学习笔记~
    用GAN进行图像压缩 by ch
    用深度学习进行图像压缩 by ch
    3D目标检测&6D姿态估计之SSD-6D算法--by leona
    如何搭建三维重建工程体系
    C++面对对象(一)
    Pybind11教程
    C++的debug和release区别
  • 原文地址:https://www.cnblogs.com/Konjakmoyu/p/5950827.html
Copyright © 2011-2022 走看看