zoukankan      html  css  js  c++  java
  • 超长数字串

    这个序列开始是: 1234567891011121314... 我们叫序列 S。然后 S[1] = 1, S[2] = 2, ... , S[10] = 1, S[11] = 0, ... , 以此类推。 
    George 现有一个数字系列 A ,他想知道在S中最早出现的位置。帮助他解决这个难题。

     

      1 #include<iostream>
      2 #include<string>
      3 using namespace std;
      4 
      5 string s;
      6 
      7 int a[300][305]={0};
      8 int flag=1;
      9 int kk=0;  
     10 //x[0~(n-m)]=s[n~m] 
     11 int getNum(int x[],int m,int n){
     12     for(int i=n;i>=m;--i)
     13     x[n-i]=s[i]-'0';
     14     }
     15 void print(int x[]){
     16      int i;
     17      for(i=300;i>=0;i--)
     18      if(x[i]!=0) break;
     19      while(i>=0) cout<<x[i--];
     20      cout<<endl;
     21      }
     22 //打印补齐后的第一个数 
     23 void print(int l){
     24      for(int i=1;i<=l;++i)
     25      cout<<s[i];
     26      cout<<endl;
     27      }
     28 //x=x+t 
     29 void add(int x[],int t){
     30      x[0]+=t;
     31      int i=0;
     32      while(x[i]>=10)
     33      {
     34        x[i+1]+=x[i]/10;
     35        x[i]%=10;
     36        i++;
     37                    }
     38      }
     39 //x=x-t 
     40 void sub(int x[],int t){
     41      x[0]-=t;
     42      int i=0;
     43      while(x[i]<0)
     44      {
     45        x[i]+=10;
     46        x[i-1]-=1;
     47        i++;
     48                    }
     49      }
     50 
     51 //前后数位数都足够 
     52 bool check(int i,int j,int m,int n){
     53      if(s[i]=='0'||s[m]=='0') return false;
     54      int x[305]={0},y[305]={0};
     55      getNum(x,i,j);
     56      getNum(y,m,n);
     57      add(x,1);
     58      for(int d=0;d<=300;d++)
     59      if(x[d]!=y[d]) return false;
     60      return true;
     61      }
     62 
     63 
     64 //后一个数位数不够,只判断后一个数与前一个数对应的位数是否相等 
     65 bool tailCheck(int i,int j,int m,int n){
     66      if(s[i]=='0'||s[m]=='0') return false;
     67      int x[305]={0},y[305]={0};
     68      getNum(x,i,j);
     69      getNum(y,m,n);
     70      add(x,1);
     71      int d1=300,d2=300;
     72      while(x[d1]==0) d1--;
     73      while(y[d2]==0) d2--;
     74      while(d1>=0&&d2>=0)
     75      {
     76         if(x[d1]!=y[d2]) return false;        
     77         d1--;d2--;        
     78                         }
     79      return true;
     80      }
     81 
     82 
     83 //判断第一个数的位数是否能为l 
     84 bool find(int l){
     85      int i,j,m,n;
     86      i=1;j=l;m=j+1;n=j+l;
     87      if(j==s.size()-1&&s[i]=='0') return false;
     88      while(true)
     89      {
     90        if(j>=s.size()-1) return true;
     91        if(n>=s.size()-1) {n=s.size()-1;if(!tailCheck(i,j,m,n)) return false;}
     92        else if(!check(i,j,m,n))  //前一个数和后一个数的位数都为l 
     93        {
     94          if(!check(i,j,m,n+1))   //前一个数位数为l,后一个数位数为l+1              
     95          return false;              
     96          else {l+=1;n+=1;}  
     97                             }
     98        i=m;
     99        j=n;
    100        m=j+1;
    101        n=j+l; 
    102              
    103              }
    104      
    105      return true;
    106      }
    107 
    108 void Multiply(int x[],int y){
    109      for(int i=0;i<=300;++i)
    110      x[i]*=y;
    111      
    112      for(int i=0;i<=300;++i)
    113      if(x[i]>9)
    114      {
    115         x[i+1]+=x[i]/10;
    116         x[i]%=10;
    117                   }
    118      }
    119 void add(int x[],int y[]){
    120      for(int i=0;i<=300;++i)
    121      x[i]+=y[i];
    122      int i=0;
    123      while(x[i]>=10)
    124      {
    125        x[i+1]+=x[i]/10;
    126        x[i]%=10;
    127        i++;
    128                    }
    129      }
    130 
    131 bool comp(int x[],int y[]){
    132      for(int i=300;i>=0;--i)
    133      if(x[i]<y[i]) return true;
    134      else if(x[i]>y[i]) return false;
    135      return false;
    136      }
    137 
    138 void getAns(int finalAns[],int l,int k){
    139      int x[305]={0},ans[305]={0};
    140      getNum(x,1,l);
    141      x[l-1]-=1;
    142      Multiply(x,l);
    143      for(int i=0;i<=300;++i)
    144      ans[i]=a[l-1][i]+x[i];
    145      ans[0]+=1+k+kk;
    146      for(int i=0;i<=300;++i)
    147      if(ans[i]>9)
    148      {
    149           ans[i+1]+=ans[i]/10;
    150           ans[i]%=10;
    151                     }   
    152      
    153      if(flag==1||comp(ans,finalAns))
    154      for(int i=0;i<=300;++i)
    155      finalAns[i]=ans[i];
    156      }
    157 //判断数组是否为1000....0000的形式 
    158 bool Equal1000(int x[]){
    159      int tot=0;
    160      for(int i=0;i<=300;++i)
    161      if(x[i]!=0) tot++;
    162      if(tot>1) return false;
    163      return true;
    164      }
    165 
    166 //判断字符串是否为全0 
    167 bool Equal000(string s1){
    168      for(int i=0;i<s1.size();++i)
    169      if(s1[i]!='0') return false;
    170      return true;
    171      }
    172 
    173      
    174 int main()
    175 { 
    176     //a[i]表示所有位数<=i的字符串长度和
    177     for(int i=1;i<=200;++i)
    178     {
    179       a[i][i-1]=9;
    180       Multiply(a[i],i);
    181       add(a[i],a[i-1]);
    182             }
    183     
    184     int finalAns[305]={0};
    185     flag=1;
    186     
    187     string s1;
    188     cin>>s1;
    189     
    190     //如果字符串=000...0,则在最前面加上0,令kk=1,最后的答案要减去kk
    191     if(Equal000(s1))
    192     {s1="1"+s1;kk=1;}
    193     
    194     //l为字符串中第一个数的位数
    195     //k表示字符串中第一个字符是第一个数的第K+1位,k<l
    196     for(int l=1;l<=s1.size();++l)
    197     for(int k=0;k<l;++k)
    198     {
    199        s=" "+s1;string s2="";
    200        if(k==0)
    201        {
    202           if(find(l))
    203              {getAns(finalAns,l,k);flag=0;}
    204                }
    205                
    206        //如果K!=0,则补齐第一个数的前k位 
    207        if(k!=0)
    208        {
    209 
    210           int x[305]={0};
    211           getNum(x,l-k+1,l-k+k);
    212           
    213           //1.直接把第l-k+1至l-k+k之间的数补齐第一个数的前k位  
    214           s2="";
    215           int i=k-1;
    216           while(i>=0) s2+=x[i--]+'0';
    217           s=" "+s2+s1;
    218           if(find(l))
    219           {getAns(finalAns,l,k);flag=0;}
    220           
    221           //2.如果第l-k+1至l-k+k之间数的形式是10....000,也可以用99....999补齐第一个数的前k位  
    222           if(Equal1000(x))
    223           {
    224              s2="";
    225              i=k-1;
    226              while(i>=0) {s2+='9';i--;}
    227              s=" "+s2+s1;
    228              if(find(l))
    229              {getAns(finalAns,l,k);flag=0;}
    230                           }
    231           //3.用第l-k+1至l-k+k之间的数减去1,补齐第一个数的前k位  
    232           sub(x,1);
    233           i=k-1;
    234           s2="";
    235           while(i>=0) s2+=x[i--]+'0';
    236           s=" "+s2+s1;
    237           if(find(l))
    238           {getAns(finalAns,l,k);flag=0;}
    239                
    240                } 
    241             
    242             }
    243     
    244     print(finalAns);        
    245                   
    246   //  system("pause");
    247     
    248     
    249 
    250     } 
  • 相关阅读:
    BZOJ2756:[SCOI2012]奇怪的游戏(最大流,二分)
    AtCoder Grand Contest
    BZOJ2565:最长双回文串(Manacher)
    BZOJ2160:拉拉队排练(Manacher)
    BZOJ3790:神奇项链(Manacher)
    BZOJ2342:[SHOI2011]双倍回文(Manacher)
    BZOJ4887:[TJOI2017]可乐(矩阵乘法)
    BZOJ2555:SubString(SAM,LCT)
    BZOJ1396:识别子串(SAM)
    luogu P1080 国王游戏
  • 原文地址:https://www.cnblogs.com/noip/p/7813951.html
Copyright © 2011-2022 走看看