ACM必做50题高精度.docx
- 文档编号:11591556
- 上传时间:2023-03-19
- 格式:DOCX
- 页数:16
- 大小:19.91KB
ACM必做50题高精度.docx
《ACM必做50题高精度.docx》由会员分享,可在线阅读,更多相关《ACM必做50题高精度.docx(16页珍藏版)》请在冰豆网上搜索。
ACM必做50题高精度
1POJ1001Exponentiation
高精度数的计算,以前在网上看到过一个计算大数阶乘比如10000000!
的算法,总体思想就是将结果用数组保存起来,然后将结果的每一位与乘数相乘,当然还有进位...
有了这个算法的思想,这个题思路就可以是:
先将输入的小数转换成一个整数,当然这个整数肯定能够用int类型的变量保存,比如1.2345,通过函数removeDot()将它转化成12345,然后利用大数阶乘的思想计算12345*12345.....*12345,最后的就是输出了,这个要考虑的情况比较多,因为这个也WA了5次才AC(笨的要死),情况虽多,但不难.
这道题是高精度计算的,不算很难,但是很繁琐,尤其是对输入输出的要求。
被这道题搞了好久,耐心来,一点一点调试,总会成功的。
#include
#include
#include
usingnamespacestd;
charans[10];
charres[2][205];
__int64ps;//有几位小数点
intlen;//长度,R的有效长度
//计算c=b*a
voidMultiply(char*b,intbt,char*a,intat,char*c)
{
inti,j;
intup=0;
for(i=0;i { up=0; for(j=0;j { intt; if(c[i+j]==0) c[i+j]='0'; t=(a[i]-48)*(b[j]-48)+c[i+j]-48+up; if(t>=10) { up=t/10; t=t%10; c[i+j]=t+48; if(j==(bt-1)) c[i+j+1]=(up+48); } else { c[i+j]=t+48; up=0; } } } } intmain() { stringstr; intn; inti,j; ints,t; intpos; while(cin>>str>>n) { i=5; pos=str.find('.',0); if(pos<0)//没有小数点 { ps=0; //zs=zs*n;//后面为0的总数 } else//有小数点 { ps=(5-pos); ps=ps*n;//小数位总数 } memset(ans,0,sizeof(ans)); memset(res[0],0,sizeof(res[0])); memset(res[1],0,sizeof(res[1])); t=5; s=0; while(str[s]=='0'||str[s]=='.') s++; j=0; for(i=t;i>=s;--i) { if(str[i]=='.') continue; ans[j]=str[i]; j++; } len=j; strcpy(res[0],ans); strcpy(res[1],ans); for(i=2;i<=n;++i) { memset(res[(i+1)%2],0,sizeof(res[0])); Multiply(res[i%2],strlen(res[i%2]),ans,len,res[(i+1)%2]); } intL=strlen(res[(n+1)%2]); intd=(n+1)%2; if(ps>0) { j=0; while(res[d][j]=='0') j++; if(ps>=L) { printf("."); for(i=ps-1;i>=j;--i) { if(i>=L) printf("0"); else printf("%c",res[(n+1)%2][i]); } } else { if(j>=ps) { for(i=L-1;i>=ps;--i) printf("%c",res[(n+1)%2][i]); } else { for(i=L-1;i>=j;--i) { if(i==ps) { printf("%c.",res[(n+1)%2][i]); } else printf("%c",res[(n+1)%2][i]); } } } } else { for(i=L-1;i>=0;--i) printf("%c",res[(n+1)%2][i]); } printf("\n"); } return0; } 2POJ1047RoundandRoundWeGo 题意: 输入一个数,要求判该数是否为循环数. 依次将该数分别于2到len(输入的数的位数)相乘,在乘的过程中,判断数发生了变化没有,如果发生了变化,则直接输出该数不是循环数,没有必要再继续乘下去,而如果是循环数,则一直需要乘下去. #include #include #include #include usingnamespacestd; intnum[70]; intans[70]; charss[70]; boolmatch[70]; intmain() { inti,j,k,len; boolflag; while(scanf("%s",ss)! =EOF) { len=strlen(ss); for(i=len-1,j=0;i>=0;i--,j++) num[j]=ss[i]-'0'; for(i=2;i<=len;i++) { memset(ans,0,sizeof(ans)); for(j=0;j ans[j]=num[j]*i; for(j=0;j if(ans[j]>=10) { ans[j+1]+=ans[j]/10; ans[j]%=10; } memset(match,0,sizeof(match));//match数组用来标记数的匹配情况 flag=true; for(j=0;j { k=0; while(k { if(ans[k]==num[j]&&! match[k])//两数字相等且没有进行标记 { match[k]=true; break; } k++; } if(k==len)//此时说明相乘后的结果发生了改变 { flag=false; break; } } if(! flag) { printf("%sisnotcyclic\n",ss); break; } } if(flag) printf("%siscyclic\n",ss); } system("pause"); return0; } 3POJ1131OctalFractions 给定一个八进制的小数题目要求你把它转换为十进制小数,转换后小数的位数是转换前八进制小数位数的3倍且不输出末尾无意义的零(即后置零).我采用的方法是乘10然后对8取整(现在假设将p进制的小数转换为n进制,同样采用乘n取整: ),每转换一位,都必须从最低位s[len-1]开始至小数的最高位(即小数点后的一位),每次计算积g=a[j]*n+k(其中k为下一位积的进位),本位进位数k=g/p,积在本位存入s[j]=g%p;最后的整数k作为转换的一位存放于转换结果字符串中。 #include #include #include #include usingnamespacestd; chars1[20],s2[50],s3[20]; intmain() { inti,t,j,k,g,l,len;; while(scanf("%s",s1)! =EOF) { l=strlen(s1); strcpy(s3,s1); len=3*(l-2); t=0; s2[0]='0'; s2[1]='.'; j=2; while(t { k=0; t++; for(i=l-1;i>1;i--)//从最低位开始采用乘10对8取整 { g=(s1[i]-'0')*10+k; k=g/8; s1[i]=g%8+'0'; } s2[j]=k+'0'; j++; } s2[j]='\0'; printf("%s[8]=",s3); j--; while(s2[j]=='0')//找出最后一个不为0的数的位置 j--; for(i=0;i<=j;i++)//去掉后置0进行的输出 printf("%c",s2[i]); printf("[10]\n"); } system("pause"); return0; } 4ACM——POJ1503(IntegerInquiry) 题目解析: 水题一道。 就是大数加法,循环移位。 注意输入数据有以0开头的整数,所以要用strcmp判断而不是直接判断[0]位是否为0。 #include #include usingnamespacestd; intmain() { //输出字符串至多为100个100位数的和,给102位,因为我不需要最后一位\0作定位符 charm_Sum[102]; //初始化这102位为'0' memset(m_Sum,48,102); //定位输出字符串的位置,用于加法。 定位输出字符串的位置,用于进位 intm_Pos_Sum,m_Pos_Sum_Temp; //输入字符串长度至多为100,给101位,因为我需要\0位控制结束 charm_Input[101]; //输入字符串的长度 intm_Length_Input; while (1) { //初始化为\0 memset(m_Input,0,101); //输入数据 scanf("%s",m_Input); //输入的数据有可能是以0开头的,不能直接判断[0]是否为0,得用strcmp if(strcmp(m_Input,"0")==0) break; else { //计算输入字符串的长度 m_Length_Input=strlen(m_Input); //定位输出字符串的位置至最后一位,即101 m_Pos_Sum=101; //从这个字符串的最低位开始加,[m_Length_Input-1]永远表示需要加的那一位 while(m_Length_Input>0) { //做单个位置的加法,注意需减48 m_Sum[m_Pos_Sum]+=(m_Input[m_Length_Input-1]-48); //定位进位位置 m_Pos_Sum_Temp=m_Pos_Sum; //如果大于9,需要进位,且是循环进位 while(m_Sum[m_Pos_Sum_Temp]>'9') { //这一位减10,前一位加1 m_Sum[m_Pos_Sum_Temp]-=10; m_Sum[--m_Pos_Sum_Temp]+=1; } //输入字符串与输出字符串均往前移1位 --m_Length_Input; --m_Pos_Sum; } } } //输出结果,先找到第一个不为0的位置 intm_Cycle; for(m_Cycle=0;m_Cycle<102;++m_Cycle) { if(m_Sum[m_Cycle]! ='0') break; } //从该位置起,输出后面所有 for(;m_Cycle<102;++m_Cycle) printf("%c",m_Sum[m_Cycle]); printf("\n"); system("pause"); return0; } 5POJ1504AddingReversedNumbers水题 此题主要就是数字的前后倒置,这是解决问题的关键,当然可以用字符串进行计算,但是这样我认为会比较复杂(没有测试),所以我采取了另一种方法,具体见reverse函数! #include intmain() { intreverse(intx); intcases,x1,x2,sum; scanf("%d",&cases); while(cases--) { scanf("%d%d",&x1,&x2); sum=reverse(x1)+reverse(x2); printf("%d\n",reverse(sum)); } return0; } intreverse(intx) { intb,sum=0; while(x! =0) { b=x%10; x=x/10; sum=sum*10+b; } returnsum; } 6poj1060(SortingItAllOut) 拓扑排序问题。 也可以用传递闭包做,但是还没有看,不会. 最主要的是要理解好题意: wherexxxisthenumberofrelationsprocessedatthetimeeitherasortedsequenceisdeterminedoraninconsistencyisfound,whichevercomesfirst,。 意思就是依次输入各个relation,一旦发现可以确定拓扑序列则输出序列,后面的relations忽略(即使发现有矛盾);一旦发现有矛盾(即环),则输出,后面relations也忽略。 这个题意我倒是一开始就理解了,但是有个简单的问题我没有想到,应该先判断是否有矛盾(环),等输完最后一个relations后再判断是否有多个拓扑序列。 如果没有考虑到这一点对于一些样例输入是可以正确输出的,但是对于如下的样例输入则会输出Sortedsequencecannotbedetermined.(实际上应该输出Inconsistencyfoundafter12relations.): 1112
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- ACM 50 高精度