• Spoj 2319 数位统计(0,1, 2^k1 这些数分成M份)


    将0,1, 2^k-1 这些数分成M份,每份的值为该份的1的数字之和 ,求使最大的那一份最小      K <=100 ,M<=100

    最大值最小化,二分的经典应用

    思路:二分这个最大值X,然后看能不能组成M份 ,然后再调整

    Cal(x):求出0-x这些数字当中1出现的次数。

            其实实际分析一下就很简单,把x化作是二进制的数,那么从高位往低位走,遇见一个1,假使这个位置在i位置,那么答案ans=ans+F[i-1]+j*2^(i-1)+1,其中j表示的是到现在位置所遇见的1的个数,F[i]表示的是0-2^i-1中所出现的1的个数,然后再加上之前出现的1的个数乘以该位出现1所经历的次数,再加上这个位置上自己出现的1的个数1,那么就是0-x出现1的次数。

    Get(t):从高位往下走,看该位置是否可以添加一个1,跟上面类似。

    View Code
      1 #include<iostream>
      2 #include<cstdio>
      3 #include<cstdlib>
      4 #include<cstring>
      5 #include<string>
      6 #include<algorithm>
      7 using namespace std;
      8 
      9 const int MAXN = 110;
     10 int const N = 120;
     11 
     12 struct bign
     13 {
     14     int len, s[MAXN];
     15     bign ()
     16     {
     17         memset(s, 0, sizeof(s));
     18         len = 1;
     19     }
     20     bign (int num)
     21     {
     22         *this = num;
     23     }
     24     bign (const char *num)
     25     {
     26         *this = num;
     27     }
     28     bign operator = (const int num)
     29     {
     30         char s[MAXN];
     31         sprintf(s, "%d", num);
     32         *this = s;
     33         return *this;
     34     }
     35     bign operator = (const char *num)
     36     {
     37         for(int i = 0; num[i] == '0'; num++);//去前导0
     38         len = strlen(num);
     39         for(int i = 0; i < len; i++)
     40             s[i] = num[len-i-1] - '0';
     41         return *this;
     42     }
     43     bign operator + (const bign &b) const //+
     44     {
     45         bign c;
     46         c.len = 0;
     47         for(int i = 0, g = 0; g || i < max(len, b.len); i++)
     48         {
     49             int x = g;
     50             if(i < len) x += s[i];
     51             if(i < b.len) x += b.s[i];
     52             c.s[c.len++] = x % 10;
     53             g = x / 10;
     54         }
     55         return c;
     56     }
     57     bign operator += (const bign &b)
     58     {
     59         *this = *this + b;
     60         return *this;
     61     }
     62     void clean()
     63     {
     64         while(len > 1 && !s[len-1]) len--;
     65     }
     66     bign operator * (const bign &b) //*
     67     {
     68         bign c;
     69         c.len = len + b.len;
     70         for(int i = 0; i < len; i++)
     71             for(int j = 0; j < b.len; j++)
     72                 c.s[i+j] += s[i] * b.s[j];
     73         for(int i = 0; i < c.len; i++)
     74         {
     75             c.s[i+1] += c.s[i]/10;
     76             c.s[i] %= 10;
     77         }
     78         c.clean();
     79         return c;
     80     }
     81     bign operator *= (const bign &b)
     82     {
     83         *this = *this * b;
     84         return *this;
     85     }
     86     bign operator - (const bign &b)
     87     {
     88         bign c;
     89         c.len = 0;
     90         for(int i = 0, g = 0; i < len; i++)
     91         {
     92             int x = s[i] - g;
     93             if(i < b.len) x -= b.s[i];
     94             if(x >= 0) g = 0;
     95             else
     96             {
     97                 g = 1;
     98                 x += 10;
     99             }
    100             c.s[c.len++] = x;
    101         }
    102         c.clean();
    103         return c;
    104     }
    105     bign operator -= (const bign &b)
    106     {
    107         *this = *this - b;
    108         return *this;
    109     }
    110     bign operator / (const int b)
    111     {
    112         bign c;
    113         int f = 0;
    114         for(int i = len-1; i >= 0; i--)
    115         {
    116             f = f*10+s[i];
    117             c.s[i]=f/b;
    118             f=f%b;
    119         }
    120         c.len = len;
    121         c.clean();
    122         return c;
    123     }
    124     bign operator / (const bign &b)
    125     {
    126         bign c, f = 0;
    127         for(int i = len-1; i >= 0; i--)
    128         {
    129             f = f*10;
    130             f.s[0] = s[i];
    131             while(f >= b)
    132             {
    133                 f -= b;
    134                 c.s[i]++;
    135             }
    136         }
    137         c.len = len;
    138         c.clean();
    139         return c;
    140     }
    141     bign operator /= (const bign &b)
    142     {
    143         *this  = *this / b;
    144         return *this;
    145     }
    146     bign operator % (const bign &b)
    147     {
    148         bign r = *this / b;
    149         r = *this - r*b;
    150         return r;
    151     }
    152     bign operator %= (const bign &b)
    153     {
    154         *this = *this % b;
    155         return *this;
    156     }
    157     bign operator ^ (const int & n) //大数的n次方运算
    158     {
    159         bign t(*this),ret(1);
    160         if(n<0) exit(-1);
    161         if(n==0) return 1;
    162         int m=n;
    163         while (m)
    164         {
    165             if (m&1) ret=ret*t;
    166             t=t*t;
    167             m>>=1;
    168         }
    169         return ret;
    170     }
    171     bool operator < (const bign &b)
    172     {
    173         if(len != b.len) return len < b.len;
    174         for(int i = len-1; i >= 0; i--)
    175             if(s[i] != b.s[i]) return s[i] < b.s[i];
    176         return false;
    177     }
    178     bool operator > (const bign &b)
    179     {
    180         if(len != b.len) return len > b.len;
    181         for(int i = len-1; i >= 0; i--)
    182             if(s[i] != b.s[i]) return s[i] > b.s[i];
    183         return false;
    184     }
    185     bool operator == (const bign &b)
    186     {
    187         return !(*this > b) && !(*this < b);
    188     }
    189     bool operator != (const bign &b)
    190     {
    191         return !(*this == b);
    192     }
    193     bool operator <= (const bign &b)
    194     {
    195         return *this < b || *this == b;
    196     }
    197     bool operator >= (const bign &b)
    198     {
    199         return *this > b || *this == b;
    200     }
    201     string str() const
    202     {
    203         string res = "";
    204         for(int i = 0; i < len; i++) res = char(s[i]+'0') + res;
    205         return res;
    206     }
    207 };
    208 
    209 istream& operator >> (istream &in, bign &x)
    210 {
    211     string s;
    212     in >> s;
    213     x = s.c_str();
    214     return in;
    215 }
    216 
    217 ostream& operator << (ostream &out, const bign &x)
    218 {
    219     out << x.str();
    220     return out;
    221 }
    222 bign pow2[N],F[N];
    223 int m,k;
    224 void pre()
    225 {
    226     pow2[0]=1;
    227     for(int i=1; i<=100; i++)pow2[i]=pow2[i-1]*2;
    228     F[1]=1;
    229     for(int i=2; i<=100; i++)F[i]=F[i-1]*2+pow2[i-1];
    230     return ;
    231 }
    232 bign cal(bign x)
    233 {
    234     bign p=0;
    235     int num[110];
    236     int top=0;
    237     while(x.len>1||x.s[0])
    238     {
    239         num[top++]=(x.s[0]%2)?1:0;
    240         x=x/2;
    241     }
    242     bign ans=0;
    243     int j=0;
    244     for(int i=top-1; i>=0; i--)
    245     {
    246         if(num[i])
    247         {
    248             ans+=(F[i]+pow2[i]*j+1);
    249             j++;
    250         }
    251     }
    252     return ans;
    253 }
    254 bign get(bign t)
    255 {
    256     bign ans=0;
    257     int j=0;
    258     for(int q=k; q>=0; q--)
    259     {
    260         bign num;
    261         if(q==0)
    262            num=j+1;
    263         else
    264            num=(F[q]+pow2[q]*j+1);
    265         if(t>=num)
    266         {
    267             ans=ans+pow2[q];
    268             t-=num;
    269             j=j++;
    270         }
    271     }
    272     return ans;
    273 }
    274 int main()
    275 {
    276     pre();
    277     cin>>k>>m;
    278     bign l=1,r=F[k],sta=pow2[k]-l;
    279         while(l<r)
    280         {
    281             bign now=0;
    282             bign mid=(l+r)/2;
    283             int i;
    284             for(i=1; i<=m; i++)
    285             {
    286                 now=get(now+mid);
    287                 if(now>=sta)break;
    288                 now=cal(now);
    289             }
    290             if(i>m)l=mid+1;
    291             else r=mid;
    292         }
    293         cout<<l<<endl;
    294     return 0;
    295 }
  • 相关阅读:
    JVM相关知识
    面试之mysql专题
    Java新特性
    数据结构操作与算法复杂度分析
    IO流
    浅谈Web安全
    面试题2
    需要知道的HTTP 知识
    How JavaScript Work
    webpack 学习笔记
  • 原文地址:https://www.cnblogs.com/nuoyan2010/p/3050515.html
Copyright © 2020-2023  润新知