超长数字串

这个序列开始是: 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     } 
时间: 2024-11-05 23:29:08

超长数字串的相关文章

【模拟】Vijos P1005 超长数字串

题目链接: https://vijos.org/p/1005 题目大意: 无限的正整数按顺序拼接成字符串S(S=12345678910111213...),给你一个字符串A(len<=200)求这个字符串在S中最早出现的位置. (答案超过long long ,无法用KMP,不要相信标签) 题目思路: [模拟] 这题简直了!!!!!!大模拟啊.细节超级多.疯狂TLE+WA+RE了17次才AC. 第一次写了一整天没写过,放了好久,昨天又写了一整天(哎效率低下.) 首先分两种普遍的情况和两种特殊情况考

解决 PHPExcel 长数字串显示为科学计数

解决 PHPExcel 长数字串显示为科学计数 https://github.com/PHPOffice/PHPExcel/ 在excel中如果在一个默认的格中输入或复制超长数字字符串,它会显示为科学计算法,例如身份证号码,解决方法是把表格设置文本格式或在输入前加一个单引号. 使用PHPExcel来生成excel,也会遇到同样的问题,解决方法有三种: 1.设置单元格为文本 $objPHPExcel = new PHPExcel(); $objPHPExcel->setActiveSheetInd

解决 PHPExcel 长数字串显示为科学计数[转]

解决 PHPExcel 长数字串显示为科学计数 在excel中如果在一个默认的格中输入或复制超长数字字符串,它会显示为科学计算法,例如身份证号码,解决方法是把表格设置文本格式或在输入前加一个单引号. 使用PHPExcel来生成excel,也会遇到同样的问题,解决方法有三种:1.设置单元格为文本 $objPHPExcel = new PHPExcel(); $objPHPExcel->setActiveSheetIndex(0); $objPHPExcel->getActiveSheet()-&

PHPExcel 长数字串显示为科学计数

解决 PHPExcel 长数字串显示为科学计数 在excel中如果在一个默认的格中输入或复制超长数字字符串,它会显示为科学计算法,例如身份证号码,解决方法是把表格设置文本格式或在输入前加一个单引号. 使用PHPExcel来生成excel,也会遇到同样的问题,解决方法有三种:1.设置单元格为文本 $objPHPExcel = new PHPExcel(); $objPHPExcel->setActiveSheetIndex(0); $objPHPExcel->getActiveSheet()-&

把数字串变成2012玛雅密码

问题: 玛雅密码是一串由0.1.2组成的密码,这串数字中如果包含2012,就可以解开末日的大门.给定一串由0.1.2组成的字符串,只有相邻的数字可以交换,求通过最少多少次变换可以得到玛雅密码,并给出这串密码. 思路: 经过很久很久的尝试,放弃了一次性拼凑2012的想法,改用预处理得到所有数字范围中符合玛雅密码的部分,再递归遍历给定的数字串,得到该串所有可能的变换,并比较每个变换的结果需要的步数. import sys def find_all_transfers(str): result={}

[华为]在字符串中找出连续最长的数字串

链接:https://www.nowcoder.com/questionTerminal/2c81f88ecd5a4cc395b5308a99afbbec来源:牛客网 样例输出 输出123058789,函数返回值9 输出54761,函数返回值5 接口说明 函数原型: unsignedint Continumax(char** pOutputstr,  char* intputstr) 输入参数:   char* intputstr  输入字符串: 输出参数:   char** pOutputst

在字符串中找出连续最长的数字串

输入描述: 输入一个字符串. 输出描述: 输出字符串中最长的数字字符串和它的长度. 输入例子: abcd12345ed125ss123058789,如果有重复的最大长度的数字串,则一起输出,如1456jk4789,输出14564789,4 输出例子: 123058789,9 思路:先把字符串中的数字串取出来,然后取出长度最大的数字字串并输出,刚开始我使用HashMap的key存储数字字串,value存字串长度,考虑到HashMap存储无序,故改为LInkedHashMap,然后根据Map的val

笔试算法题(37):二叉树的层序遍历 &amp; 最长递增的数字串

出题:要求层序遍历二叉树,从上到下的层次,每一层访问顺序为从左到右,并将节点一次编号,输出如下:如果只要求打印指定的level的节点,应该如何实现. a b  c d  e  f  g h  i  分析: 原始的层序遍历类似于BFS,打印当前访问的节点curNode的序列号,并将其直接子节点放入队列queue中,然后从queue中取出下一个节点,直 到队列为空:此方法仅能按照层序打印所有节点,并不能区分每一层节点的数量:如果需要区分当前层次的节点,和当前层次节点的子节点,可以使用两个队列 que

比较字符串和数字串(轉載)

比较字符串 和数字串 要比较字符 串(类型 C)和数字 文本(类型 N),可以 在逻辑表达 式中使用下 列运算符. <运算符>含 义 CO 仅包 含 CN 不仅 包含 CA 包 含任何 NA 不 包含任何 CS 包 含字符串 NS 不 包含字符串 CP 包含模 式 NP 不包 含模式 因为除类型 N和 C 外,系统不 能执行任何 其它类型转 换,所以, 在进行包含 这些运 算之 一的比较时 ,操作数应 该是类型 N 或 C. 运算符的功 能如下: CO (仅包含) 如果 <F1>