解题思路:
针对数据的特点n<=25普通的大数乘法即可,算法不难,主要是输入的处理有点复杂,很容易漏掉!
WA的请注意。输入数据需要考虑R和n的特殊情况!
分情况讨论:R:1,整数2,小数
然后对于每一种情况又分有无前导零,后导零。
R:000000 000100
R:小数点可以在任意位置如:.00000 000.00 00000.
n注意为0的情况!
优化前代码:在PKU能过,在杭电TLE,郁闷了下(杭电上还是有很多变态数据的....)
优化前代码:
POJ Accepted 168K 16MS C++ 1692B
HDU Time Limit Exceeded 1063 500MS 220K 1748 B
CODE(1):优化前
#include <iostream> #include <string.h> #define N 200 int in[N],out[N],temp[N]; char ans[N]; void A(char *s) { int len = strlen(s); char *p = s + len - 1; if (strchr(s, '.')) while (!(*p>='1'&&*p<='9')&&*p!='.') *p-- = '/0';//让*p='/0',然后p--; if (*p == '.') *p = '/0'; } void multiply(int a[N],int b[N],int c[N]) { int i,j,w=0,v=0; for(i=0;i<N;i++)//初始化 c[i]=0; for(i=0;i<N;i++) for(j=0;j<N;j++) c[i+j]+=a[i]*b[j];//很巧妙 for(i=0;i<N-1;i++)//进位处理 { c[i+1]+=c[i]/10; c[i]%=10; } } int main () { char *pa,a[20]; int i,b,k,j; while(scanf("%s %d",a,&b)!=EOF) { memset(in,0,sizeof(in)); memset(temp,0,sizeof(temp)); memset(out,0,sizeof(out)); memset(ans,'/0',sizeof(ans)); if(b==0) {printf("1/n");continue;} int flag=-12,flag1=0;//标记输入的是否是整数 for(k=0,i=strlen(a)-1;i>=0;i--) { if(a[i]=='.') flag=strlen(a)-i-1;//记录小数点位子,即小数点后有几位 else in[k++]=a[i]-'0'; } for(i=0;i<k;i++) temp[i]=out[i]=in[i]; int tt=k-1; while(out[tt]==0&&tt>=0) tt--;//n==1时去前导0 if(tt<0) {printf("0/n");flag1=1;continue;} int T=b-1;//要乘的次数 while(T--) { multiply(in,temp,out); memcpy(temp,out,N*sizeof(int)); } //int pos=flag*b; if(flag==-12)//输入为整数的情况 { i=N-1; while(!temp[i]) i--; if(i<0) printf("0"); for(;i>=0;i--) printf("%d",temp[i]); printf("/n"); } else { int pos=flag*b; for(i=0,j=N-1;i<N;i++,j--) { if(i<pos) ans[j]=out[i]+'0'; else if(i==pos) ans[j]='.'; else ans[j]=out[i-1]+'0'; } pa=ans; A(pa); while(*pa=='0') pa++; puts(pa); } } return 0; }
优化后代码:
OPJ Accepted 168K 0MS C++ 1759B
HDU Accepted 1063 46MS 248K 1898 B C++
CODE(2):优化后
#include <iostream> #include <string.h> #define N 160 int in[N],out[N],temp[N]; char ans[N]; void A(char *s)//小数点后零的处理 { int len = strlen(s); char *p = s + len - 1; if (strchr(s, '.')) while (!(*p>='1'&&*p<='9')&&*p!='.') *p-- = '/0';//让*p='/0',然后p--; if (*p == '.') *p = '/0'; } void multiply(int a[N],int b[N],int c[N])//大数乘法 { int i,j,w=0,v=0,m,n; for(i=0;i<N;i++)//初始化 c[i]=0; m=n=N-1;//进行时间上的优化 while(!a[m]&&m>0) m--; while(!b[n]&&n>0) n--; for(i=0;i<=m;i++) for(j=0;j<=n;j++) c[i+j]+=a[i]*b[j];//很巧妙 for(i=0;i<N-1;i++)//进位处理 { c[i+1]+=c[i]/10; c[i]%=10; } } int main () { char *pa,a[20]; int i,b,k,j; while(scanf("%s %d",a,&b)!=EOF) { memset(in,0,sizeof(in));//初始化 memset(temp,0,sizeof(temp)); memset(out,0,sizeof(out)); memset(ans,'/0',sizeof(ans)); if(b==0)//b==0时的特殊处理 {printf("1/n");continue;} int flag=-12;//标记输入的是否是整数 for(k=0,i=strlen(a)-1;i>=0;i--) { if(a[i]=='.') flag=strlen(a)-i-1;//记录小数点位子,即小数点后有几位 else in[k++]=a[i]-'0'; } for(i=0;i<k;i++) temp[i]=out[i]=in[i]; int tt=k-1; while(out[tt]==0&&tt>=0) tt--;//n==1时去前导0 if(tt<0) {printf("0/n");continue;} int T=b-1;//要乘的次数 while(T--) { multiply(in,temp,out); memcpy(temp,out,N*sizeof(int));//将out复制给temp } //int pos=flag*b; if(flag==-12)//输入为整数的情况 { i=N-1; while(!temp[i]) i--; if(i<0) printf("0"); for(;i>=0;i--) printf("%d",temp[i]); printf("/n"); } else//小数情况 { int pos=flag*b; for(i=0,j=N-1;i<N;i++,j--) { if(i<pos) ans[j]=out[i]+'0'; else if(i==pos) ans[j]='.'; else ans[j]=out[i-1]+'0'; } pa=ans; A(pa); while(*pa=='0') pa++; puts(pa); } } return 0; } /* 附录,别人的一些数据: 95.123 12 0.4321 20 5.1234 15 6.7592 9 98.999 10 1.0100 12 .00001 1 .12345 1 0001.1 1 1.1000 1 10.000 1 000.10 1 000000 1 000.00 1 .00000 0 000010 1 000.10 1 0000.1 1 00.111 1 0.0001 1 0.0001 3 0.0010 1 0.0010 3 0.0100 1 0.0100 3 0.1000 1 0.1000 3 1.0000 1 1.0000 3 1.0001 1 1.0001 3 1.0010 1 1.0010 3 1.0100 1 1.0100 3 1.1000 1 1.1000 3 10.000 1 10.000 3 10.001 1 10.001 3 10.010 1 10.010 3 10.100 1 10.100 3 99.000 1 99.000 3 99.001 1 99.001 3 99.010 1 99.010 3 99.100 1 99.100 3 99.998 1 99.998 3 */