大整数运算(PAT B1017,PAT A1023,PAT A1024)

对一道A+B的题目来说,如果A和B都是有几十位甚至1000位的整数,就需要用特殊的方法来求解。即大整数运算。

大整数运算

很简单,用数组储存即可,整数的高位存储在数组的高位,整数的低位存储在数组的低位
定义结构体:

struct bign{
	int d[1000];
	int len;
	bign(){
		memset(d,0,sizeof(d));
		len = 0;
	} // 构造函数
}

在输入大数时,一般用字符串读入,再把字符串另存到bign结构体中,需要让字符串倒着赋给d[]数组

bign change(char str[]){
	bign a;
	a.len = strlen(str);
	for(int i = 0; i < a.len;i++){
		a.d[i] = str[a.len-1-i] - '0';
	}
	return a;
}

大整数的四则运算

加法:

bign add(bign a,bign b){
	bign c;
	int carry; // carry是进位
	for(int i = 0; i < a.len || i < b.len;i++){
		int temp = a.d[i] + b.d[i] + carry;
		c.d[c.len++] = temp % 10;
		carry = temp / 10;
	}
	if (carry != 0){
		c.d[c.len++] = carry;
	}
	return c;
}

减法,同样是一个很简练的步骤:对于某一步,比较被减位和减位,如果不够减,则令被减位的高位数减1,被减位加10再进行减法;如果够减,则直接减。最后一步要注意减法后高位可能有多余的0,要除去它们,但也要保证结果至少有一位数

bign sub(bign a,bign b){
	bign c;
	for(int i = 0 ; i < a.len || i < b.len; i++){
		if (a.d[i] < b.d[i]){
			a.d[i+1]--;
			a.d[i] += 10;
		}
		c.d[c.len++] = a.d[i] - b.d[i];
	}
	while(c.len -1 >= 1 && c.d[c.len - 1] == 0){
		c.len--;
	}
	return c;
}

高精度与低精度的乘法
需要的是始终把低精度看为一个整体

bign multi(bign a,bign b){
	bign c;
	int carry = 0; // 进位
	for(int i = 0; i < a.len;i++){
		int temp = a.d[i]*b +carry;
		c.d[c.len++] = temp % 10;
		carry = temp / 10;
	}
	while(carry){
		c.d[c.len++] = carry % 10;
		carry /= 10;
	}
	return c; 
}

高精度与低精度的除法
上一步的余数乘以10再加上该步的位,得到该步临时的被除数,将其与除数比较:如果不够除,则该位的商为0;如果够除,则商即为对应的商,余数即为对应的余数。最后一步要注意减法后高位可能有多余的0,要去除它们,但同样要保证结果至少有一位。

bign divide(bign a,int b,int& r){
	bign c;
	c.len = a.len; // 被除数的每一位和商的每一位是一一对应的,因此先令长度相等
	for(int i = a.len -1; i >= 0; i--){ // 从高位开始
		r = r*10 + a.d[i];
		if (r < b)c.d[i] = 0;
		else{
			c.d[i] = r /b;
			r = r % b;	
		}
	}
	while (c.len -1 >= 0 && c.d[c.len] == 0){
		c.len--;
	}
	return 0;
}

1017 A除以B (20point(s))

本题要求计算 A/B,其中 A 是不超过 1000 位的正整数,B 是 1 位正整数。你需要输出商数 Q 和余数 R,使得 A=B×Q+R 成立。

输入格式:

输入在一行中依次给出 A 和 B,中间以 1 空格分隔。

输出格式:

在一行中依次输出 Q 和 R,中间以 1 空格分隔。

输入样例:

123456789050987654321 7

输出样例:

17636684150141093474 3

思路:
直接套模版
代码:

#include<cstdio>
#include<cstring>
struct bign
{
	int d[1000];
	int len;
	bign(){
		memset(d,0,sizeof(d));
		len = 0;
	}
};

bign change(char str[]){
	bign a;
	a.len = strlen(str);
	for (int i = 0; i < a.len; ++i)
	{
		a.d[i] = str[a.len -1 -i] - '0';
	}
	return a;
}

bign divide(bign a,int b,int& r){
	bign c;
	c.len = a.len;
	for(int i = a.len-1; i >= 0;i--){
		r = r*10 + a.d[i];
		if (r < b)c.d[i] = 0;
		else{
			c.d[i] = r/b;
			r = r % b;
		}
	}
	while(c.len-1 >= 1 && c.d[c.len-1] == 0){
		c.len--;
	}
	return c;
}

int main(){
	char str[1000];
	int b,r = 0;
	scanf("%s %d",str,&b);
	bign c = divide(change(str),b,r);
	for(int i = c.len-1; i >= 0;i--){
		printf("%d",c.d[i] );
	}
	printf(" %d\n", r);
	return 0;
}

1023 Have Fun with Numbers(20point(s))

Notice that the number 123456789 is a 9-digit number consisting exactly the numbers from 1 to 9, with no duplication. Double it we will obtain 246913578, which happens to be another 9-digit number consisting exactly the numbers from 1 to 9, only in a different permutation. Check to see the result if we double it again!
Now you are suppose to check if there are more numbers with this property. That is, double a given number with k digits, you are to tell if the resulting number consists of only a permutation of the digits in the original number.

Input Specification:

Each input contains one test case. Each case contains one positive integer with no more than 20 digits.

Output Specification:

For each test case, first print in a line “Yes” if doubling the input number gives a number that consists of only a permutation of the digits in the original number, or “No” if not. Then in the next line, print the doubled number.

Sample Input:

1234567899

Sample Output:

Yes
2469135798

思路:这道题可以用等于两大数相加或高精度与低精度相乘来求解,直接套上述模版就行,需要注意的是,题目要判断这两个数是否只是排列不同,所以需要写一个Judge函数
函数开头应先判断 这两个数长度是否相同。如果相同,则要继续判断,这两个大数中出现0-9的次数是否相等,我们可以开一个count[10] = {0}数组,遍历一遍大数a和b,因为a.len == b.len ,所以我们只需要写一个遍历就行,在for中 如果出现a的元素,count[a]++,如果出现b的元素count[b]–;如果遍历完后count数组的每个元素都是0,表示相同return true,反之。
代码:

#include<cstdio>
#include<cstring>
struct bign
{
	int d[1000];
	int len;
	bign(){
		memset(d,0,sizeof(d));
		len = 0;
	}
};

bign change(char str[]){
	bign a;
	a.len = strlen(str);
	for (int i = 0; i < a.len; ++i)
	{
		a.d[i] = str[a.len - 1 - i] - '0';
	}
	return a;
}

bign multi(bign a,int b){
	bign c;
	int carry = 0;
	for(int i = 0; i < a.len;i++){
		int temp = a.d[i]*b + carry; 
		c.d[c.len++] = temp % 10;
		carry = temp / 10;
	}
	while (carry){
		c.d[c.len++] = carry % 10;
		carry /= 10;
	}
	return c;
}

bool Judge(bign a,bign b){
	if (a.len != b.len )return false;
	int count[10] = {0};
	for(int i = 0; i < a.len;i++){
		count[a.d[i]]++;
		count[b.d[i]]--;
	}
	for(int i = 0; i < 10;i++){
		if (count[i])return false;
	}
	return true;
}

int main(){
	char str[100];
	scanf("%s",str);
	bign a = change(str);
	bign b = multi(a,2);
	if (Judge(a,b)){
		printf("Yes\n");
	}else{
		printf("No\n");
	}
	for(int i = b.len-1;i>=0;i--){
		printf("%d",b.d[i]);
	}
	return 0;
}

1024 Palindromic Number(25point(s))

A number that will be the same when it is written forwards or backwards is known as a Palindromic Number. For example, 1234321 is a palindromic number. All single digit numbers are palindromic numbers.
Non-palindromic numbers can be paired with palindromic ones via a series of operations. First, the non-palindromic number is reversed and the result is added to the original number. If the result is not a palindromic number, this is repeated until it gives a palindromic number. For example, if we start from 67, we can obtain a palindromic number in 2 steps: 67 + 76 = 143, and 143 + 341 = 484.
Given any positive integer N, you are supposed to find its paired palindromic number and the number of steps taken to find it.

Input Specification:

Each input file contains one test case. Each case consists of two positive numbers N and K, where N (≤1010) is the initial numer and K (≤100) is the maximum number of steps. The numbers are separated by a space.

Output Specification:

For each test case, output two numbers, one in each line. The first number is the paired palindromic number of N, and the second number is the number of steps taken to find the palindromic number. If the palindromic number is not found after K steps, just output the number obtained at the Kth step and K instead.

Sample Input 1:

67 3

Sample Output 1:

484
2

palindromic 回文结构
思路:
题意是让一个整数加上这个整数颠倒之后的数,在给定的k次内加下去看是否能构成回文串。
用大数来存储是比较方便的方式。
首先要写一个Judge函数来判断是否是回文字符串

bool Judge(bign a){
	for(int i = 0; i <= a.len/2; i++){
		if (a.d[i] != a.d[a.len -i -1])return false;
	}
	return true;
}

在题目给定的操作次数内重复,每次将当前数倒置得到一个新的数,再将原数与新数使用大整数相加,赋回给原数,直到产生一个回文数或到达操作次数后停止

#include<cstdio>
#include<cstring>
struct bign
{
	int d[1000];
	int len;
	bign(){
		memset(d,0,sizeof(d));
		len = 0;
	}
};

bign change(char str[]){
	bign a;
	a.len = strlen(str);
	for(int i = 0; i < a.len;i++){
		a.d[i] = str[a.len-1-i] -'0';
	}
	return a;
}

bign add(bign a,bign b){
	bign c;
	int carry = 0;
	for(int i = 0; i < a.len || i < b.len;i++){
		int temp = a.d[i] + b.d[i] +carry;
		c.d[c.len++] = temp % 10;
		carry = temp / 10;
	}
	if (carry){
		c.d[c.len++] = carry;
	}
	return c;
}

bign reverse(bign a){
	bign c;
	c.len = a.len;
	for(int i = 0; i < c.len;i++){
		c.d[i] = a.d[a.len-1-i];
	}
	return c;
}

bool Judge(bign a){
	for(int i = 0; i <= a.len/2;i++){
		if (a.d[i] != a.d[a.len-1-i])return false;
	}
	return true;
}

int main(){
	char str[100];
	int step;
	int k = 0;
	scanf("%s %d",str,&step);
	bign a = change(str);
	while(k < step && Judge(a) == false){
		bign b = reverse(a);
		a = add(a,b);
		k++;
	}
	for(int i = a.len-1;i >= 0; i--){
		printf("%d",a.d[i]);
	}
	printf("\n");
	printf("%d\n", k);
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值