ACM必做50题的解题高精度.docx

上传人:b****5 文档编号:3414113 上传时间:2022-11-22 格式:DOCX 页数:16 大小:19.72KB
下载 相关 举报
ACM必做50题的解题高精度.docx_第1页
第1页 / 共16页
ACM必做50题的解题高精度.docx_第2页
第2页 / 共16页
ACM必做50题的解题高精度.docx_第3页
第3页 / 共16页
ACM必做50题的解题高精度.docx_第4页
第4页 / 共16页
ACM必做50题的解题高精度.docx_第5页
第5页 / 共16页
点击查看更多>>
下载资源
资源描述

ACM必做50题的解题高精度.docx

《ACM必做50题的解题高精度.docx》由会员分享,可在线阅读,更多相关《ACM必做50题的解题高精度.docx(16页珍藏版)》请在冰豆网上搜索。

ACM必做50题的解题高精度.docx

ACM必做50题的解题高精度

POJ1001Exponentiation

高精度数的计算,以前在网上看到过一个计算大数阶乘比如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;

}

 

POJ1047RoundandRoundWeGo

题意:

输入一个数,要求判该数是否为循环数.

依次将该数分别于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;

}

 

POJ1131OctalFractions

给定一个八进制的小数题目要求你把它转换为十进制小数,转换后小数的位数是转换前八进制小数位数的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;

}

 

ACM——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;

}

 

POJ1504AddingReversedNumbers水题

此题主要就是数字的前后倒置,这是解决问题的关键,当然可以用字符串进行计算,但是这样我认为会比较复杂(没有测试),所以我采取了另一种方法,具体见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;

}

 

poj1060(SortingItAllOut)

拓扑排序问题。

也可以用传递闭包做,但是还没有看,不会.

最主要的是要理解好题意:

wherexxxisthenumberofrelationsprocessedatthetimeeitherasortedsequenceisdeterminedoraninconsistencyisfound,whichevercomesfirst,。

意思就是依次输入各个relation,一旦发现可以确定拓扑序列则输出序列,后面的relations忽略(即使发现有矛盾);一旦发现有矛盾(即环),则输出,后面relations也忽略。

这个题意我倒是一开始就理解了,但是有个简单的问题我没有想到,应该先判断是否有矛盾(环),等输完最后一个relations后再判断是否有多个拓扑序列。

如果没有考虑到这一点对于一些样例输入是可以正确输出的,但是对于如下的样例输入则会输出Sortedsequencecannotbedetermined.(实际上应该输出Inconsistencyfoundafter12relations.):

1112

K

B

E

D

G

H

G

I

J

A

F

C

再注意到这一点就可以避免错误了,应该就差不多能过了。

#include

usingnamespacestd;

classpoly{

public:

poly(intN=0){

n=N;

p=newint[n*sizeof(int)];

for(inti=0;i

}

poly&operator=(constpoly&s){

n=s.n;

for(inti=n-1;i>=0;i--)

p[i]=s.p[i];

while(!

s.p[n-1])n--;

return*this;

}

~poly(){if(p)delete[]p;}

voidset(constpoly&a,constpoly&b){

n=abs(a.n-b.n)+1;

for(inti=0;i

p[n-1]=1;

}

friendpolyoperator*(constpoly&a,constpoly&b){

polyd(a.n+b.n+1);

d.n=1;

inti,j;

for(i=0;i

if(a.p[i])

for(j=0;j

if(b.p[j]){

d.p[i+j]=(d.p[i+j]+1)%2;

if(i+j>d.n-1)d.n=i+j+1;

}

returnd;

}

friendpolyoperator-(constpoly&a,constpoly&b){

polyd(max(a.n,b.n));

for(inti=0;i

d.p[i]=(a.p[i]-b.p[i])%2;

if(d.p[i]<0)d.p[i]+=2;

}

returnd;

}

friendbooloperator>(constpoly&a,constpoly&b){

if(a.n>b.n)return1;

if(a.n==b.n)

for(inti=a.n-1;i>=0;i--)

if(a.p[i]>b.p[i])return1;

return0;

}

friendostream&operator<<(ostream&out,constpoly&s){

cout<

for(inti=s.n-1;i>=0;i--)

cout<<''<

returnout;

}

friendistream&operator>>(istream&in,poly&s){

cin>>s.n;

for(inti=s.n-1;i>=0;i--)

cin>>s.p[i];

returnin;

}

private:

intn,*p;

}a(1001),b(1001),c(1001),d(2002),e(1001);

intmain()

{

intt;

cin>>t;

while(t--){

cin>>a>>b>>c;

d=a*b;

while(d>c){

e.set(d,c);

d=d-c*e;

}

cout<

}

}

 

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 解决方案 > 工作计划

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1