zoukankan      html  css  js  c++  java
  • 【模拟】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 */
    View Code
  • 相关阅读:
    【LeetCode】3. Longest Substring Without Repeating Characters
    【LeetCode】65. Valid Number
    【LeetCode】8. String to Integer (atoi)
    【Java】 大话数据结构(18) 排序算法(5) (直接插入排序)
    【LeetCode】557. Reverse Words in a String III
    【LeetCode】151. Reverse Words in a String
    【LeetCode】28. Implement strStr()
    【LeetCode】125. Valid Palindrome
    【Java】 遍历HashMap
    【LeetCode】170. Two Sum III – Data structure design
  • 原文地址:https://www.cnblogs.com/Coolxxx/p/5790341.html
Copyright © 2011-2022 走看看