Description
倒数,顾名思义就是用1除以被倒数得出的结果,例如2的倒数是0.5,0.5的倒数是2。现在我们需要获得正有理数的倒数。
正有理数的表示格式:
<整数部分> + [小数点]+ [小数非循环部分] [(循环部分)]
其中 <> 为必填部分, []为可选部分, 如果选了小数点,则后面肯定有小数部分
正有理数的表示要求:
整数部分十位数字以后不能有多余的0,如 00123 是非法的有理数
小数后面不能有多余的0,如 0.123000 , 0.12(0) 是非法的有理数
可以放进循环部分的小数一定要放进循环部分,不能留在非循环部分,如 0.123(3) ,12.123234(234) 是非法的
小数循环部分不能是 (9),如果是(9)则需要进一处理,如 0.(9)=1 , 0.2(9)=0.3
Input
输入只有一行,代表一个正有理数,符合上述的有理数表示要求,每一行最多100个字符。
Output
输出一行,代表输入的正有理数的倒数,要求符合上述有理数的表示要求。
输入数据保证输出的正确答案不超过100个字符。
Sample Input
Sample Input1 3 Sample Input2 0.(3)
Sample Output
Sample Output1 0.(3) Sample Output2 3
Solution
高精度。
对于循环节之前的部分,写成a/b的形式,a,b为整数,b为10的非负整数次方。
对于循环节部分,设X=0.0000(abcde),设S=0.(abcde),
则10^5S=abcde.(abcde)
10^5S-S=99999S=abcde
S=abcde/99999
X=S/10^4
这样就能表示出来了。
设循环节可以写成c/d
那么答案=1/(a/b+c/d)=1/( (ad+bc) / bd )=bd/(ad+bc)
先除一遍,输出整数部分。
如果如数为0则停止;
如果不为0,则:
再将小数点后面的部分乘以10^100,
再除一遍,
如果余数为0则直接省略最后面的0输出;
如果不为0,枚举一段数作为循环节,判断和下一段连续的数是否相等,知道找到循环节为止。时间复杂度是三次方。
Code
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<cstdlib>
#define I int
#define F(i,a,b) for(I i=a;i<=b;i++)
#define Fd(i,a,b) for(I i=a;i>=b;i--)
#define mem(a,b) memset(a,b,sizeof a)
#define N 1000
#define M 10
using namespace std;
I a[N],b[N],c[N],d[N],t[N],p,len,bz;
char s[N];
void up(I o[]){
F(i,1,o[0]){o[i+1]+=o[i]/M;o[i]%=M;}
while(o[o[0]+1]){
o[0]++;
o[o[0]+1]+=o[o[0]]/M,o[o[0]]%=M;
}
}
void time(I o[]){F(i,1,o[0]) o[i]*=10;}
void TM(I A[],I B[]){
mem(t,0);
t[0]=A[0]+B[0]-1;
if(!A[0]||!B[0]) t[0]=0;
F(i,1,A[0]){
F(j,1,B[0]){
t[i+j-1]+=A[i]*B[j];
t[i+j]+=t[i+j-1]/M;
t[i+j-1]%=M;
}
}
up(t);
}
I cmp(I A[],I B[]){
if(A[0]>B[0]) return 1;
if(A[0]<B[0]) return 0;
Fd(i,A[0],1){
if(A[i]>B[i]) return 1;
if(A[i]<B[i]) return 0;
}
return 1;
}
void dec(I C[],I T[]){
F(j,1,T[0]) C[j]-=T[j];
F(j,1,T[0]){
while(C[j]<0){C[j]+=M,C[j+1]--;}
}
while(C[0]&&!C[C[0]]) C[0]--;
}
void div(){
mem(c,0);mem(d,0);
Fd(i,b[0],1){
time(c);c[1]+=b[i];up(c);
Fd(j,9,0){
mem(t,0);
t[0]=a[0];
F(k,1,a[0]) t[k]=a[k]*j;
up(t);
if(cmp(c,t)){d[i]=j;dec(c,t);break;}
}
}
d[0]=b[0];
while(!d[d[0]]) d[0]--;
}
I main(){
freopen("numdiv.in","r",stdin);
freopen("numdiv.out","w",stdout);
scanf("%s",s+1),len=strlen(s+1);
F(i,1,len){
if(s[i]=='.') p=i;if(s[i]=='(') bz=i;
if(s[i]=='.'||s[i]=='('||s[i]==')') continue;
if(bz){time(c),c[1]+=s[i]-'0',up(c);}
else{time(a),a[1]+=s[i]-'0',up(a);}
}
b[0]=b[1]=1;
I tim=bz?bz-p-1:(p?len-p:len-1);
while(tim--){time(b),up(b);}
if(bz){
tim=len-bz-1;
while(tim--){time(d);d[1]+=9;up(d);}
tim=bz-p-1;
while(tim--){time(d);up(d);}
}
else d[0]=d[1]=1;
TM(a,d);F(i,0,t[0]) a[i]=t[i];//a*d
TM(c,b);F(i,0,t[0]) c[i]=t[i];//c*b
a[0]=max(a[0],c[0]);F(i,1,c[0]) a[i]+=c[i];up(a);//a*d+c*b
TM(b,d);F(i,0,t[0]) b[i]=t[i];//b*d
//ans=b/a
if(cmp(b,a)){ //b>=a
div();
Fd(i,d[0],1) printf("%d",d[i]);
TM(d,a);dec(b,t);
if(!b[0]) return 0;
else printf(".");
}
else printf("0.");
F(i,1,100){time(b);up(b);}
div();
if(!c[0]){
len=1;
while(!d[len]) len++;
Fd(i,100,len) printf("%d",d[i]);
return 0;
}
Fd(i,100,1){
Fd(j,i,1){
len=i-j+1;
bz=1;
F(k,1,len) if(d[i-k+1]!=d[j-1-k+1]){bz=0;break;}
if(bz){
Fd(k,100,i+1) printf("%d",d[k]);
printf("(");
Fd(k,i,j) printf("%d",d[k]);
printf(")");
return 0;
}
}
}
return 0;
}