传送门:http://acm.hdu.edu.cn/showproblem.php?pid=5920
我们的思路是:
- 对于一个串s,先根据s串前一半复制到后一半构成一个回文串,
- 如果这个回文串比s小,则做减法并递归;
- 如果相等直接结束;
- 如果大,那么找前一半离中心最近的一个非零数减1,并把这位之后到中心的数全都变为9,例如11000->11011,大了,所以变成10901;
ps:因为大数相减要传指针参数,调了蛮久,发现指针的乱指了,所以开了一个二维数组,每一次算出的原串和回文串都用新的指针,也就是s[tot],ss[tot],temp[tot];
/************************************************************** Problem: User: youmi Language: C++ Result: Accepted Time: Memory: ****************************************************************/ //#pragma comment(linker, "/STACK:1024000000,1024000000") //#include<bits/stdc++.h> #include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <map> #include <stack> #include <set> #include <sstream> #include <cmath> #include <queue> #include <deque> #include <string> #include <vector> #define zeros(a) memset(a,0,sizeof(a)) #define ones(a) memset(a,-1,sizeof(a)) #define sc(a) scanf("%d",&a) #define sc2(a,b) scanf("%d%d",&a,&b) #define sc3(a,b,c) scanf("%d%d%d",&a,&b,&c) #define scs(a) scanf("%s",a) #define sclld(a) scanf("%I64d",&a) #define pt(a) printf("%d\n",a) #define ptlld(a) printf("%I64d\n",a) #define rep(i,from,to) for(int i=from;i<=to;i++) #define irep(i,to,from) for(int i=to;i>=from;i--) #define Max(a,b) ((a)>(b)?(a):(b)) #define Min(a,b) ((a)<(b)?(a):(b)) #define lson (step<<1) #define rson (lson+1) #define eps 1e-6 #define oo 0x3fffffff #define TEST cout<<"*************************"<<endl const double pi=4*atan(1.0); using namespace std; typedef long long ll; template <class T> inline void read(T &n) { char c; int flag = 1; for (c = getchar(); !(c >= '0' && c <= '9' || c == '-'); c = getchar()); if (c == '-') flag = -1, n = 0; else n = c - '0'; for (c = getchar(); c >= '0' && c <= '9'; c = getchar()) n = n * 10 + c - '0'; n *= flag; } ll Pow(ll base, ll n, ll mo) { ll res=1; while(n) { if(n&1) res=res*base%mo; n>>=1; base=base*base%mo; } return res; } //*************************** int n; const int maxn=1000+10; const ll mod=1000000007; char ans[100][maxn]; int tot=0; int Minus(char *source1, char *source2, char *result)//返回:1(s1>s2),-1(s1<s2),0(s1=s2) { int length1 = strlen(source1); // 被减数的长度 int length2 = strlen(source2); // 减数的长度 int i, j, k = 0; int temp; // 临时存放位相减的结果 int bit = 0; // 借位,1表示需要借位,0表示不需要借位 char ch; // 用于交换 for (i = length1 - 1, j = length2 - 1; i >= 0 && j >= 0; --i, --j) { // 计算两个位之间的差值,同时要考虑借位 temp = (source1[i] - '0') - (source2[j] - '0') - bit; if (temp < 0) // 需要借位 { bit = 1; result[k++] = temp + 10 + '0'; } else// 不需要借位 { bit = 0; result[k++] = temp + '0'; } } while (i >= 0) // length1 > length2的情况,结果为正数,将剩余数据赋值给计算结果数组 { temp = source1[i--] - '0' - bit; if (temp < 0) // 需要借位 { bit = 1; result[k++] = temp + 10 + '0'; } else { bit = 0; result[k++] = temp + '0'; } } while (j >= 0)// length1 < length2的情况,结果为负数,将剩余数据赋值给计算结果数组 { temp = 10 - bit - (source2[j--] - '0'); result[k++] = temp + '0'; } // 对仍有进位的情况考虑,主要分两种:一种是strlen(p1)<strlen(p2),另一种是p1-p2<0,这两种情况bit为1 if (bit == 1) { // 最低位肯定不会被借位,所以不需要减去借位 // 只会向高位借位 result[0] = 10 - (result[0] - '0') + '0'; for (i = 1; i < k; i++) { result[i] = 10 - (result[i] - '0') - bit + '0'; } } for (i = k - 1, j = 0; i >= j; --i, ++j) { ch = result[i]; result[i] = result[j]; result[j] = ch; } result[k] = '\0'; while(result[0]=='0'&&strlen(result)>1)//去掉前导零 strcpy(result,result+1); if(length1<length2) return -1; else if(length1>length2) return 1; else { for(int i=0;i<length1;i++) { if(source1[i]>source2[i]) return 1; else if (source1[i]<source2[i]) return -1; } } return 0; } char ss[100][maxn],temp[100][maxn]; char s[100][maxn]; void dfs() { int len=strlen(s[tot]); if(len==1) { strcpy(ans[tot],s[tot]); tot++; return; } int half=len/2; int pre=-1; int num=1-len%2; if(len%2==0) { for(int i=0;i<half;i++) { if(s[tot][i]!='0') pre=max(pre,i); ss[tot][i]=s[tot][i]; } for(int i=half;i<len;i++) ss[tot][i]=ss[tot][2*half-i-1]; } else { for(int i=0;i<=half;i++) { if(s[tot][i]!='0') pre=max(pre,i); ss[tot][i]=s[tot][i]; } for(int i=half+1;i<len;i++) ss[tot][i]=ss[tot][2*half-i]; } ss[tot][len]='\0'; s[tot][len]='\0'; int flag=Minus(s[tot],ss[tot],temp[tot]); if(flag==-1) { if(s[tot][pre]=='1'&&pre==0) { for(int i=0;i<len-1;i++) ss[tot][i]='9'; ss[tot][len-1]='\0'; } else { ss[tot][pre]=s[tot][pre]-1; ss[tot][2*half-pre-num]=s[tot][pre]-1; for(int i=pre+1;i<2*half-pre-num;i++) ss[tot][i]='9'; } Minus(s[tot],ss[tot],temp[tot]); strcpy(ans[tot],ss[tot]); strcpy(s[tot+1],temp[tot]); tot++; dfs(); } else if(flag==0) { strcpy(ans[tot],ss[tot]); tot++; return; } else { strcpy(ans[tot],ss[tot]); strcpy(s[tot+1],temp[tot]); tot++; dfs(); } } int main() { int kase=0; sc(n); while(n--) { printf("Case #%d:\n",++kase); tot=0; scs(s[tot]); while(s[tot][0]=='0'&&strlen(s[tot])>1)//去掉前导零 strcpy(s[tot],s[tot]+1); dfs(); pt(tot); rep(i,0,tot-1) puts(ans[i]); } return 0; }
不为失败找借口,只为成功找方法