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