又一道ACM大赛的题 求俩个大数的和,c语言,大数不超过1000位 的正整数

又一道ACM大赛的题 求俩个大数的和,c语言,大数不超过1000位 的正整数,第1张

#include <stdioh>

#include <stringh>

int main()

{

int t,i;

scanf("%d",&t);

for(i=1;i<=t;i++)

{

int ka,kb,k,f,j,p;

char a[1001],b[1001],s[1001];

scanf("%s",a);

scanf("%s",b);

ka = strlen(a);

kb = strlen(b);

k = ka < kb kb : ka;

ka--;

kb--;

f = 0;

s[k] = 0;

for(j=k-1;j>=0;j--)

{

p = f;

if(ka>=0) p+=a[ka]-'0';

if(kb>=0) p+=b[kb]-'0';

if(p>9)

{

p-=10;

f=1;

}

else f=0;

s[j] = p+'0';

ka--;

kb--;

}

printf("Case %d:\n",i);

printf("%s + %s = ",a,b);

if(f) putchar('1');

printf("%s\n",s);

if(i!=t) putchar(10);

}

}

刚刚那个

#include <stdioh>

#include <stringh>

int main()

{

char a[1001],b[1001],c[1002],d[1002],e[1002];

int n,i,j,lena,lenb,lenmax,jin;

e[1001] = 0;

scanf("%d",&n);

for(i=1;i<=n;i++)

{

if(i>1) putchar(10);

scanf("%s%s",a,b); / 读取a和b /

lena = strlen(a); / 获取a的长度 /

memset(c,'0',sizeof(c)); / 清空c /

strcpy(c+1001-lena,a); / 把a复制到c中, 右对齐 /

lenb = strlen(b); / 获取b的长度 /

lenmax = lena>lenblena:lenb; / 计算a和b的长度的较大值 /

memset(d,'0',sizeof(d)); / 清空d /

strcpy(d+1001-lenb,b); / 把b复制到d中, 右对齐 /

jin = 0; / 进位 /

for(j=1000;j>=1000-lenmax;j--) /把c和d从个位开始做模拟加法 /

{

e[j] = c[j] - '0' + d[j] + jin; / 算出e /

jin = 0; / 取消进位 /

if(e[j]>'9') / 需要进位 /

{

e[j]-=10;

jin=1;

}

}

printf("Case %d:\n%s + %s = ",i,a,b);

if(e[1000-lenmax]=='0') printf("%s\n",e+1001-lenmax); / 如果e的开头为0, 则跳过0 /

else printf("%s\n",e+1000-lenmax); / 否则直接打印 /

}

}

///程序是在 ConsolAppcation 中运行的直接复制代码到类里面就可以运行 没有增加异常处理 使用请合理输入

using System;

using SystemCollectionsGeneric;

using SystemLinq;

using SystemText;

namespace ConsoleApplication2

{

class Program

{

static void Main(string[] args)

{

while(true)

{

int[] arr = new int[5];

arr[0] = intParse(ConsoleReadLine());

arr[1] = intParse(ConsoleReadLine());

arr[2] = intParse(ConsoleReadLine());

arr[3] = intParse(ConsoleReadLine());

arr[4] = intParse(ConsoleReadLine());

for (int i = 0; i < arrLength; i++)

ConsoleWrite(arr [i]+",");

ConsoleWriteLine("求出最大值为:");

int max= getMax(arr);

ConsoleWrite(max);

ConsoleReadKey();

}

}

private static int getMax(int[] arr)

{

int x = arr[0];

for (int i=1; i < arrLength; i++)

{

if (x < arr[i])

{

x = arr[i];

}

}

return x;

}

}

}

#include<stdioh>

int max(int a,int b,int c)

{

int max=a;

if(b>max)

max=b;

if(c>max)

max=c;

return max;

}

main()

{

int a,b,c;

float m;

scanf("%d%d%d",&a,&b,&c);

m=10max(a,b,c)/(max(a+b,b,c)max(a,b,b+c));

printf("%3f",m);

}

这是代码,如果要用,要先自己调试一下才行。

struct Node // 定义一个双向链表用来存贮结果

{

char data; // 数据定义为字符的原因:要显示负号

Node next; // 尾指针

Node ahead; // 首指针

};

/--------------------------------------------------------------------------

函数名称: 大数加法

函数过程:1 比较两个数那一个长

2 以长的作为循环次数

3 对应项相加 进位存贮直到下高位相加用

4 直到循环结束

5 !!!!!!没设计负数相加

入口参数:numa,numb,result字符串

出口参数:无

编辑环境:winSP2 + VC2003 + C++

--------------------------------------------------------------------------/

void addition(char numa, char numb,char result) // 计算两大数之和

{

char pna = findend(numa); // 指向numa的一个指针。point numa pna 指向乘数的最低位,

char pnb = findend(numb); //指向numb的一个指针 //pnb 指向被乘数的最低位,

int along=(int)strlen(numa); //标记数字a的长度;

int blong=(int)strlen(numb); //标记数字b的长度;

int times = 0; // 标致要计算多少次。

int carry=0,temp_result; //存贮进位 和临时结果的

Node head, // 用于存贮头指针

pstart, // 用于存贮计算时的首指针

pnew; //作于申请新结点

head = pstart =new Node; //初始化首结点和头结点。

pstart -> data = 0;

pstart -> next = NULL;

pstart -> ahead = NULL;

if (abigerb(numa ,numb)>=1)

times = (int)strlen(numa); //比较两个字符串长度,以大的作为循环次数

else

{

times = (int)strlen(numb);

pna = findend(numb); //交换指针

pnb = findend(numa);

along=(int)strlen(numb); //标记数字a的长度;

blong=(int)strlen(numa); //标记数字b的长度;

}

while ((times-- && (times>=0))|| carry != 0)

{

if(!pstart->next) //如果当前为空结点,则申请新结点

{

pnew = new Node;

pnew -> data = 0;

pnew -> next = NULL;

pnew -> ahead = pstart;

pstart -> next = pnew;

}

else temp_result =(pstart->data +(pna-48)+(pnb-48)+carry) ; //自身的值+新值+进位 作为当前的新值

pstart -> data = temp_result%10; //存贮个位

carry = temp_result/10; //存贮进位

pstart = pstart -> next; //结点移动

blong--;

if(blong>0)pnb--; //指针移向被加数高位

else pnb=48; //之后相减就变为了0不作任何运算;

pna--; //加数指针移动,

}

pstart =head; //寻找链表的结尾点

while(pstart->next != 0)

{

pstart->data += 48; //!!<<<因为我们的输出是字符。所以再此加上48>>>> 逆顺输出

pstart = pstart->next ;

}

int tip = 0; //转为字符串用

pstart = pstart->ahead ; //找有效字

//cout<<"\n结果是 : ";

while(pstart != 0) //输出正序的结果;

{

result[tip++] = pstart->data;

//cout< data;

pstart = pstart->ahead ;

}

result[tip] = '\0';

pstart =head; //释放空间

while(pstart->next != 0)

{

pnew = pstart->next ;delete pstart;

pstart =pnew;

}

return ;

}

//比较两个数字符串大小的函数

//返回值说明:0是alongblong ; 2是along=blong

int abigerb(char numa, char numb) //比较两个数最高位那一个大

{

int along=(int)strlen(numa); //标记数字a的长度;

int blong=(int)strlen(numb); //标记数字b的长度;

char pna = numa; //指向数A的最高位,

char pnb = numb; //指向数B的最高位,

if (along>blong) return 1;

if (along==blong)

{

while(pna) //比较两个数那一个大

{

if(pna>pnb)return 1;

else if(pna<pnb)return 0 ;

else if(pna==pnb) //1111与1112

}

return 2; //这表明找到最后了还是全相等;

}

return 0 ;

}

/--------------------------------------------------------------------------

函数名称: 大数减法

函数过程:1 比较两个数那一个长

2 以长的作为循环次数

3 如果两个数长度相等,从最高位开始比直到发现那一个数更大,使大项减去小项

4 对应项相减 进位存贮直到下高位相加用

5 每一位对应项相减时,处理三种可能的情况,a=b,ab;

6 a=b时,则计算,11-12,111-112,要考虑借位

7 直到循环结束

入口参数:numa,numb,result字符串

出口参数:无

--------------------------------------------------------------------------/

void subtract(char numa, char numb,char result)//计算减

{ char pna = findend(numa);//指向numa的一个指针。point numa pna 指向减数的最低位,

char pnb = findend(numb);//指向numb的一个指针 //pnb 指向被减数的最低位,

int along=(int)strlen(numa);//标记数字a的长度;

int blong=(int)strlen(numb);//标记数字b的长度;

int times = 0; // 标记要计算多少次。

int carry=0; //存贮借位

int clear0=0; //消除结果最前面无用的'0' 13-5 = 08 的效果!!

int isnegative=0; //用来加上被减数大于减数时补上最后一个负号

Node head, // 用于存贮头指针

pstart, // 用于存贮计算时的首指针

pnew; //作于申请新结点

head = pstart =new Node;//初始化首结点和头结点。

pstart -> data = 0;

pstart -> next = NULL;

pstart -> ahead = NULL;

if (abigerb(numa ,numb))

times = strlen(numa);//比较两个字符串长度,以大的作为循环次数

else //交换位置以降低难度

{

times = strlen(numb);//让数(字符串)长的减去数(字符串)短的

pna = findend(numb);//交换指针

pnb = findend(numa);

along=(int)strlen(numb);//标记数字a的长度;

blong=(int)strlen(numa);//标记数字b的长度;

isnegative=1;//标记最后要加上负号

}

while ((times-- && (times>=0))|| carry != 0)//carry != 0 说没有借位时

{

if(!pstart->next)//如果当前为空结点,则申请新结点

{

pnew = new Node;

pnew -> data = 0;

pnew -> next = NULL;

pnew -> ahead = pstart;

pstart -> next = pnew;

}

if(times<0)//如果计算完之后,借位等于1,,说明必然为负值;

{ pstart -> data = -3 ;//让它等于负号 '-'//-3来源于负号与0相差3。。

break; }

else

{

if ( pna == pnb )//减数等于被减数时。结果等于直截相减的结果;并置借位为0

{

if(carry==0)pstart -> data = (pna-48)-(pnb-48); //111-11的情况

else

{

pstart->data = (pna-48)-(pnb-48)+10 -carry;//1121-1112 carry=1;

}

}

if( pna > pnb )//减数大于被减数时。结果等于直截相减的结果;并置借位为0

{

pstart -> data = (pna-48)-(pnb-48)-carry; //存贮个位

carry=0;

}

else if( pna < pnb )//说明被减数大于减数,让结果加10,相当于借位 (carry)为1

{ if(times>0)

pstart->data = (pna-48)-(pnb-48)+10 -carry;//13-5的情况作为新值

else

pstart->data = (pnb-48)-(pna-48) -carry; //3-5 作为当前的新值

carry=1;

}

}

pstart = pstart -> next;

//结点移动

blong--;

if(blong>0)pnb--;//指针移向被减数高位

else pnb=48;//之后相减就变为了0不作任何运算,其实可以优化的。但代码会长!而且还需要重新开结点。所以放弃; pna--;//被数指针移动,

}

if(isnegative==1)////加上负号处理。增加一长度并置为负号

{

pnew = new Node;

pnew -> data = 0;

pnew -> next = NULL;

pnew -> ahead = pstart;

pstart -> next = pnew;

pstart->data=-3;//因为寻找链表的结尾点要统一加48。又因为‘-’是45。所以等于‘-3’

}

pstart =head;//寻找链表的结尾点

while(pstart->next != 0)

{

pstart->data += 48;//!!<<<因为我们的输出是字符。所以再此加上48>>>> 逆顺输出

pstart = pstart->next ;

}

int tip = 0;//转为字符串用

clear0=0;// 消除结果最前面无用的'0' 13-5 = 08 的效果 >>修改字符串的首指针

pstart = pstart->ahead ;//找有效字

while(pstart != 0)//输出正序的结果;

{ if(clear0==0 && ((int)pstart->data)==48&&pstart->ahead!=0)// 消除结果最前面无用的'0' ;

//不输出任何东西

else

result[tip++] = pstart->data;

if(((int)pstart->data)!=48&&((int)pstart->data)!=45)clear0=1;//'-'号

pstart = pstart->ahead ;

}

result[tip] = '\0';

pstart =head; //释放空间

while(pstart->next != 0)

{

pnew = pstart->next ;

delete pstart;

pstart =pnew;

}

return ;

}

/--------------------------------------------------------------------------

函数名称: 大数乘法

函数过程:1 输入两个大数作为字符串

2 作一个双向链表

3 两个指针分别指向数字字符串的最低位

4 以第一个数的最低的一个位乘以第二个数的所有项存于链表中

5 链表首指针移

6 重复4,5依次从最低位乘到最高位

7 乘完后因为最低位是链表首,最后一位是链表尾。所以在逆顺输出链表。

4 直到循环结束

入口参数:numa,numb,result字符串

出口参数:无

--------------------------------------------------------------------------/

void multiply(char numa, char numb ,char result)//用来储结果的)//计算乘积

{ char pna = findend(numa);//指向numa的一个指针。point numa pna 指向乘数的最低位,

char pnb = findend(numb);//指向numb的一个指针

//pnb 指向被乘数的最低位,

int along=(int)strlen(numa);//标记数字a的长度;

int blong=(int)strlen(numb);//标记数字b的长度;

int carry=0,temp_result;//存贮进位 和临时结果的

Node head, // 用于存贮头指针

pstart, // 用于存贮计算时的首指针

pnew, //作于申请新结点

pgo; //作为每计算完一行时,回到下一行起始节点用,移位标致来用

head = pstart =new Node;//初始化首结点和头结点。

pstart -> data = 0;

pstart -> next = NULL;

pstart -> ahead = NULL;

while (along--)

{

pgo = pstart;//保存进位点

blong = (int)strlen(numb);//初始化长度

pnb = findend(numb); //初始化指针

while ((blong-- && (blong>=0))|| carry != 0)

{ if(!pstart->next)//如果当前为空结点,则申请新结点

{ pnew = new Node;

pnew -> data = 0;

pnew -> next = NULL;

pnew -> ahead = pstart;

pstart -> next = pnew;

}

if(blong<0)temp_result = carry ;//处理只有进位的情况

else temp_result =(pstart->data+(pna-48)(pnb-48)+carry);//自身值+新值+进位作为新值

pstart -> data = temp_result%10; //存贮个位

carry = temp_result/10; //存贮进位

pstart = pstart -> next; //结点移动

pnb--; //指针移向被乘数高位

}

pstart = pgo->next; //前进一个位置;

pna--; //指针移向乘数高位

}

pstart =head;//寻找链表的结尾点

while(pstart->next != 0) {

pstart->data += 48;//!!<<<因为我们的输出是字符。所以再此加上48>>>> 逆顺输出

pstart = pstart->next ; }

int tip = 0;//转为字符串用

pstart = pstart->ahead ;//找有效字

while(pstart != 0)//输出正序的结果;

{ result[tip++] = pstart->data;

pstart = pstart->ahead ; }

result[tip] = '\0';

pstart =head; //释放空间

while(pstart->next != 0) {

pnew = pstart->next ;

delete pstart;

pstart =pnew;

}

return ;

}

/--------------------------------------------------------------------------

函数名称: 大数除法2--

函数想法:1 用指针指向除数的最高位,保存临时字符串; tempstr[a++] = pna

2 如果临时字符串大于被除数,则相减。结果等于余数

if(tempstr>numb)tempstr = tempstr - numb

3 如果小于被除数且指针到头,余数 等于 临时字符串

if(tempstr

入口参数:numa,numb,result,remainder字符串

出口参数:无

--------------------------------------------------------------------------/

void divide2( char numa, char numb,char result,char remainder)//计算除法2

{ char one[]="1";//临时字符串

char one2[]="1";//

char zero[]="0";//

char numb2[6048];//

char tempstr[6018]="";//临时字符串 i

nt ia=0,ia2=0;//tempstr的指示器

bool moveon=false;//翻转牌

char pna = numa;//指向numa的一个指针point numa pna //指向减数的最低位,

char pnb = findend(numb);//指向numb的一个指针 //pnb 指向被减数的最低位,

Node head, // 用于存贮头指针

pstart, // 用于存贮计算时的首指针

pnew; //作于申请新结点

head = pstart =new Node;//初始化首结点和头结点。

pstart -> data = 0;

pstart -> next = NULL;

pstart -> ahead = NULL;

moveon = false; while(pna)

{ if(!pstart->next)//如果当前为空结点,则申请新结点

{ pnew = new Node;

pnew -> data = 0;

pnew -> next = NULL;

pnew -> ahead = pstart;

pstart -> next = pnew; }

ia=(int)strlen(tempstr);//取的长度

tempstr[ia++] = (pna++);

tempstr[ia] ='\0'; //转换为字符串

if(tempstr[0]=='0')//处理高位也是0的那种 如00

{

ia2=0;

while(tempstr[ia2]=='0')++ia2;

while(ia2>=1)//清除无用的0

{

ia=ia2-1;

tempstr[ia]=tempstr[ia2];

--ia2;

}

tempstr[++ia2]='\0';

}

while(abigerb(tempstr,numb)>0)//如果tempstr大于等于numb

{

if(tempstr[0]=='0')//处理高位也是0的那种 如00----此乃冗余代码,留做记念用

{

ia2=0;

while(tempstr[ia2]=='0')++ia2;

if(ia==ia2 )

}

strcpy(numb2,numb);

subtract(tempstr, numb,tempstr);//A-B strcpy(numb,numb2);

if(tempstr[0]=='-')//若判断的不准,变为了负数就再加上B。。

{

strcpy(numb2,numb);

addition(tempstr, numb,tempstr);//A-B

strcpy(numb,numb2);

ia2=0; //修正之后的长度。因为加法中未做负数运算

ia=0; //为了消除最后的那一个负号,整体向前移动。

while(tempstr[ia2]!='\0')++ia2;

while(ia2>=1)//清除无用的0 {

tempstr[ia]=tempstr[ia+1];

++ia;

--ia2; }

tempstr[ia]='\0';

moveon = true;

break; }

pstart->data++ ; //结果自加

moveon = true; }

if(moveon) pstart = pstart -> next; //结点移动

}

strcpy(remainder,tempstr);//存贮余数

int tip = 0;//转为字符串用

pstart =head;//寻找链表的结尾点

while(pstart->next != 0) {

pstart->data += 48;//!!<<<因为我们的输出是字符。所以再此加上48>>>> 逆顺输出

result[tip++] = pstart->data;

pstart = pstart->next ; }

result[tip] = '\0';//存贮结果

pstart =head; //释放空间

while(pstart->next != 0) {

pnew = pstart->next ;delete pstart; pstart =pnew; }

return ;

}

另外,虚机团上产品团购,超级便宜

scanf("%d", &n); n不能这样的,数组需要预先定义大小,不能在运行时输入大小

一下修改完毕

#include <stdioh>

#define N 10

int main1()

{

int i,n,a[N];

scanf("%d", &n);

for (i=0;i<n;i++)

scanf("%d",&a[i]);

for (i=0;i<n-1;i++)

{

for (int j=i;j<n-1;j++)

{

if (a[j]>a[j+1])

{

int tmp = a[j];

a[j] = a[j+1];

a[j+1] = tmp;

}

}

}

printf("%d\n", a[n-1]);

printf("%d\n", a[n-2]);

return 0;

}

写的一个C++实现10000的阶乘的代码

#include<iostream>

#define N 10000//设阶乘数为10000

#define SIZE 40000//预留40000位保存结果

using namespace std;

void mul(int n1,int n2)//两数相乘

{

for(int i=0;i!=SIZE;++i)

n1[i]=n2;

for(int i=0;i!=SIZE;++i){

n1[i+1]+=(n1[i]/10);

n1[i]%=10;

}

}

int main()

{

int num=new int[SIZE];

memset(num,0,SIZE);

num[0]=1;

//N的阶乘

for(int i=1;i!=N+1;++i){

mul(num,i);

}

//输出时排除开头的0

for(int i=SIZE-1;i!=-1;--i){

if(0!=num[i]){

for(int j=i;j!=-1;--j){

cout <<num[j];

}

break;

}

}

delete[] num;

return 0;

}

很多地方不合理,尤其是需要预留空间,这就要我先预算一下会有多少位了。运算时间20秒左右,效率也不行,应该在10秒左右比较合理,机器为P3 733,内存256MB。

以上就是关于又一道ACM大赛的题 求俩个大数的和,c语言,大数不超过1000位 的正整数全部的内容,包括:又一道ACM大赛的题 求俩个大数的和,c语言,大数不超过1000位 的正整数、用c#编写程序求5个数中的最大数(数据由用户从键盘输入)、c语言最大数max(x,y,z)等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zz/10167967.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-05-06
下一篇 2023-05-06

发表评论

登录后才能评论

评论列表(0条)

保存