【模拟】Vijos P1005 超长数字串

题目链接:

  https://vijos.org/p/1005

题目大意:

  无限的正整数按顺序拼接成字符串S(S=12345678910111213...),给你一个字符串A(len<=200)求这个字符串在S中最早出现的位置。

  (答案超过long long ,无法用KMP,不要相信标签)

题目思路:

  【模拟】

  这题简直了!!!!!!大模拟啊。细节超级多。疯狂TLE+WA+RE了17次才AC。

  第一次写了一整天没写过,放了好久,昨天又写了一整天(哎效率低下。)

  首先分两种普遍的情况和两种特殊情况考虑。

  普遍情况一是S串是由三段组成,头,尾和中间数字串,头尾可能不完全。这时候枚举中间数字串的长度和起始位置,就可以判断出最早出现的数字

  (如:123[98 12399 124]00  99[8 999 1000 10]01 等)

  (一开始我是想把这个再分情况考虑,发现有进位什么的太麻烦了后来直接把这个数压到高精度中,先-1判断和头是否匹配,再每次+1判断和后面的字符串匹不匹配,尾部同理)

  普遍情况二是S串是由两段组成,前面的数字的尾部和后面的数字的头部组成,这时要枚举重叠部分的长度和断开的位置。

  (如:1[2 1]3  123[699 1237]00    60211602应该是 1[6021 1602]2 而不是[60211 602]12)

  (一开始我忘记了这种情况WA了好久。。感觉自己好蠢。)

  特殊情况一是全为0的情况,这是都不符合上面的情况,就需要在头部再添上一个1,肯定是最早出现的。

  特殊情况二是全为9的情况,除了单个9是9以外,两位数以上的9都可以拆成 8[9999... 9]0000... 这个答案明显比[9999...] 10000...优。

  (不知道自己还有没有漏情况,希望没有吧,望指教。)

  

  1 //
  2 //by coolxxx
  3 //#include<bits/stdc++.h>
  4 #include<iostream>
  5 #include<algorithm>
  6 #include<string>
  7 #include<iomanip>
  8 #include<map>
  9 #include<memory.h>
 10 #include<time.h>
 11 #include<stdio.h>
 12 #include<stdlib.h>
 13 #include<string.h>
 14 //#include<stdbool.h>
 15 #include<math.h>
 16 #define min(a,b) ((a)<(b)?(a):(b))
 17 #define max(a,b) ((a)>(b)?(a):(b))
 18 #define abs(a) ((a)>0?(a):(-(a)))
 19 #define lowbit(a) (a&(-a))
 20 #define sqr(a) ((a)*(a))
 21 #define swap(a,b) ((a)^=(b),(b)^=(a),(a)^=(b))
 22 #define mem(a,b) memset(a,b,sizeof(a))
 23 #define eps (1e-8)
 24 #define J 10
 25 #define mod 1000000007
 26 #define MAX 0x7f7f7f7f
 27 #define PI 3.14159265358979323
 28 #define N 404
 29 using namespace std;
 30 typedef long long LL;
 31 int cas,cass;
 32 int n,m,lll,ans;
 33 double anss;
 34 char s[N];
 35 int a[N],b[N],t[N],c[N];
 36 void gjdchange(int a[],int l,int r)//l~r中间的字符转化为高精度数a
 37 {
 38     int i;
 39     mem(t,0);
 40     t[0]=r-l+1;
 41     for(i=1;i<=r-l+1;i++)
 42         t[i]=s[r-i+1]-‘0‘;
 43     memcpy(a,t,sizeof(t));
 44 }
 45 void plu(int a[])//高精度a+1
 46 {
 47     int i;
 48     for(i=1,a[1]++;a[i]>=J;i++)
 49         a[i]-=J,a[i+1]++;
 50     a[0]=max(a[0],i);
 51 }
 52 void dec(int a[])//高精度a-1
 53 {
 54     int i;
 55     for(i=1,a[1]--;a[i]<0;i++)
 56         a[i]+=J,a[i+1]--;
 57     while(!a[a[0]] && a[0]>1)a[0]--;
 58 }
 59 int gjdbigger(int a[],int b[])//高精度a和高精度b比大小  1:a>b  0:a<b  -1:a=b
 60 {
 61     if(a[0]!=b[0])return a[0]>b[0];
 62     int i;
 63     for(i=a[0];i;i--)if(a[i]!=b[i])return a[i]>b[i];
 64     return -1;
 65 }
 66 bool tou(int i,int len)//判断头部是否满足
 67 {
 68     int ii;
 69     dec(a);
 70     for(ii=1;ii<=a[0] && i-ii;ii++)
 71         if(a[ii]!=s[i-ii]-‘0‘)return 0;
 72     return 1;
 73 }
 74 void gjdjia(int a[],int b[],int c[])//高精度a+高精度b,答案存在高精度c里
 75 {
 76     int i;
 77     mem(t,0);
 78     t[0]=max(a[0],b[0]);
 79     for(i=1;i<=t[0];i++)
 80         t[i]=a[i]+b[i];
 81     for(i=1;i<=t[0];i++)
 82         t[i+1]+=t[i]/J,t[i]%=J;
 83     while(t[t[0]+1])t[0]++;
 84     while(!t[t[0]] && t[0]>1)t[0]--;
 85     memcpy(c,t,sizeof(t));
 86 }
 87 void gjdjian(int a[],int b[],int c[])//高精度a-高精度b,答案存在高精度c里
 88 {
 89     int i;
 90     mem(t,0);
 91     t[0]=a[0];
 92     for(i=1;i<=t[0];i++)
 93         t[i]=a[i]-b[i];
 94     for(i=1;i<=t[0];i++)
 95         if(t[i]<0)t[i+1]--,t[i]+=J;
 96     for(i=1;i<=t[0];i++)
 97         t[i+1]+=t[i]/J,t[i]%=J;
 98     while(t[t[0]+1])t[0]++;
 99     while(!t[t[0]] && t[0]>1)t[0]--;
100     memcpy(c,t,sizeof(t));
101 }
102 void gjdchengdjd(int a[],int b,int c[])//高精度a*单精度b,答案存在高精度c里
103 {
104     int i;
105     mem(t,0);
106     t[0]=a[0]+3;
107     for(i=1;i<=a[0];i++)
108         t[i]=a[i]*b;
109     for(i=1;i<=t[0];i++)
110         t[i+1]+=t[i]/J,t[i]%=J;
111     while(t[t[0]+1])t[0]++;
112     while(!t[t[0]] && t[0]>1)t[0]--;
113     memcpy(c,t,sizeof(t));
114 }
115 void cal(int len,int head)//已知a为第一个完整出现的数字,len为长度,head为出现的位置
116 {
117     int i,j;
118     int tmp[N];
119     mem(tmp,0);
120     //gjdchange(a,head,head+len-1);
121     b[0]=1;b[1]=9;c[0]=1;c[1]=0;
122     for(i=1;i<a[0];i++)
123     {
124         gjdchengdjd(b,i,tmp);
125         gjdjia(c,tmp,c);
126         b[b[0]+1]=9;b[b[0]++]=0;
127     }
128     b[b[0]]=0;
129     b[0]=a[0];b[b[0]]=1;
130     for(i=1;i<a[0];i++)b[i]=0;
131     gjdjian(a,b,a);
132     gjdchengdjd(a,len,b);
133     gjdjia(c,b,c);
134     mem(b,0);
135     b[0]=1;b[1]=head-2;
136     while(b[b[0]]>=J)b[b[0]+1]=b[b[0]]/J,b[b[0]++]%=J;
137     gjdjian(c,b,c);
138 }
139 void work(int &len,int &head)//从中间断开分成两个数字的情况
140 {
141     int i,j,l;
142     if(len<=n)
143         gjdchange(a,head,head+len-1);
144     else a[0]=MAX;
145     b[0]=0;
146     for(l=0;l<=(n+1)/2+1;l++)//最终长度n-l
147     {
148         for(j=1;j<=l;j++)
149             if(s[j]!=s[n-l+j])break;
150         if(j<=l)continue;
151         for(i=l+2;i<=n-l;i++)
152         {
153             b[0]=0;
154             for(j=i-1;j;j--)b[++b[0]]=s[j]-‘0‘;
155             for(j=n-l;j>=i;j--)b[++b[0]]=s[j]-‘0‘;
156             plu(b);
157             if(b[b[0]]==0)continue;
158             for(j=0;j<b[0] && i+j<=n;j++)
159                 if(b[b[0]-j]!=s[i+j]-‘0‘)break;
160             if(j<b[0] && i+j<=n)continue;
161             if(gjdbigger(a,b)){memcpy(a,b,sizeof(b));len=n-l;head=i;}
162         }
163     }
164 }
165 bool all9()//长度大于2且全是9的特殊情况 拆成8999999999...+9000000000...
166 {
167     int i;
168     gjdchange(b,1,n);
169     for(i=1;i<=b[0];i++)if(b[i]!=9)return 0;
170     if(b[0]==1)return 0;
171     b[b[0]]=8;plu(b);
172     memcpy(a,b,sizeof(b));
173     return 1;
174 }
175 bool all0()//全是0的特殊情况 1+00000000...
176 {
177     int i;
178     gjdchange(b,1,n);
179     for(i=1;i<=b[0];i++)if(b[i]!=0)return 0;
180     b[++b[0]]=1;
181     memcpy(a,b,sizeof(b));
182     return 1;
183 }
184 void gjdprint(int a[])//输出高精度a
185 {
186     int i;
187     printf("%d",a[a[0]]);
188     for(i=a[0]-1;i;i--)
189         printf("%d",a[i]);
190     puts("");
191 }
192 int main()
193 {
194     #ifndef ONLINE_JUDGE
195     freopen("1.txt","r",stdin);
196 //    freopen("2.txt","w",stdout);
197     #endif
198     int i,j,k,l;
199 //    for(scanf("%d",&cas);cas;cas--)
200 //    for(scanf("%d",&cas),cass=1;cass<=cas;cass++)
201     while(~scanf("%s",s+1))
202 //    while(~scanf("%d",&n))
203     {
204         s[0]=‘.‘;
205         n=strlen(s)-1;
206         for(l=1;l<=n;l++)
207         {
208             for(i=1;i<=l && i+l-1<=n;i++)
209             {
210                 gjdchange(a,i,i+l-1);
211                 if(a[a[0]]==0)continue;//前导0不符合要求
212                 if(i!=1)
213                 {
214                     if(!tou(i,l))continue;
215                     plu(a);
216                 }
217                 for(j=i+l;j<=n;j+=a[0])
218                 {
219                     plu(a);
220                     for(k=0;j+k<=n && k<a[0];k++)
221                     {
222                         if(a[a[0]-k]!=s[j+k]-‘0‘)break;
223                     }
224                     if(j+k>n || k<a[0])break;
225                 }
226                 if(j+k>n)break;
227                 if(j>n)break;
228             }
229             if(i<=l && i+l-1<=n)break;
230         }
231         //以上是将字符串拆成三段枚举,头,尾和中间的数字
232         work(l,i);
233         if(all9())cal(n,n);
234         else if(all0())cal(n+1,0);
235         else cal(l,i);
236         gjdprint(c);
237     }
238     return 0;
239 }
240 /*
241 //
242
243 //
244 */

时间: 2024-11-05 21:39:12

【模拟】Vijos P1005 超长数字串的相关文章

超长数字串

这个序列开始是: 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

解决 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>