机试编程(五)——数学问题(二)

机试编程(五)——数学问题(二)

目录:

  1. 基础知识
    1. 大整数运算
    2. 快速幂
    3. 矩阵与矩阵快速幂
  2. 应用实例
    1. a^b【牛客竞赛】
    2. 求root(N, k)【清华大学】
    3. 计算两个矩阵的乘积【哈尔滨工业大学】
    4. 矩阵幂【北京邮电大学】
    5. A+B for Matrices【浙江大学】
    6. 递推数列【清华大学】
    7. 大整数运算:a+b【华中科技大学】
    8. N的阶乘【清华大学】
    9. 数字阶梯求和【哈尔滨工业大学】
    10. 大整数的因子【北京大学】

一、基础知识

1、大整数运算

  • 整数的数值太大,无法用任何内置整数类型来保存,对于这些数值巨大的整数,需要进行处理。
  • 大整数运算模板(加减乘除、取模、输入、输出等)。

示例模板及代码:

#include <iostream>
#include <string>
#include <cstring>

using namespace std;

const int MAX_N = 1000;

//模板
struct BigInteger{
	int digit[MAX_N];
	int length;
	BigInteger();
	BigInteger(int x);
	BigInteger(string str);
	BigInteger(const BigInteger &b);
	bool operator<=(const BigInteger &b);
	bool operator==(const BigInteger &b);
	BigInteger operator*(const BigInteger &b);
	BigInteger operator+(const BigInteger &b);
	BigInteger operator-(const BigInteger &b);
	BigInteger operator/(const BigInteger &b);
	BigInteger operator%(const BigInteger &b);
	BigInteger operator=(string str);
	BigInteger operator=(int x);
	BigInteger operator=(const BigInteger &b);
	template <class T>
	friend istream& operator>>(istream &in, BigInteger &x);
	template <class T>
	friend ostream& operator<<(ostream &out, const BigInteger &x);
};

istream& operator>>(istream &in, BigInteger &x){
	string str;
	in >> str;
	x = str;
	return in;
}

ostream& operator<<(ostream &out, BigInteger &x){
	for(int i = x.length - 1; i >= 0; i--){
		out << x.digit[i];
	}
	return out;
}

BigInteger::BigInteger(){
	memset(digit, 0, sizeof(digit));
	length = 0;
}

BigInteger::BigInteger(int x){
	memset(digit, 0, sizeof(digit));
	length = 0;
	if(x == 0){
		digit[length++] = x;
	}
	while(x != 0){
		digit[length++] = x % 10;
		x /= 10;
	}
}

BigInteger::BigInteger(string str){
	memset(digit, 0, sizeof(digit));
	length = str.size();
	for(int i = 0; i < length; i++){
		digit[i] = str[length - i - 1] - '0';
	}
}

BigInteger::BigInteger(const BigInteger &b){
	memset(digit, 0, sizeof(digit));
	length = b.length;
	for(int i = 0; i < length; i++){
		digit[i] = b.digit[i];
	}
}

BigInteger BigInteger::operator=(int x){
	memset(digit, 0, sizeof(digit));
	length = 0;
	if(x == 0){
		digit[length++] = 0;
	}
	while(x != 0){
		digit[length++] = x % 10;
		x /= 10;
	}
	return *this;
}

BigInteger BigInteger::operator=(string str){
	memset(digit, 0, sizeof(digit));
	length = str.size();
	for(int i = 0; i < length; i++){
		digit[i] = str[length - i - 1] - '0';
	}
	return *this;
}

BigInteger BigInteger::operator=(const BigInteger &b){
	memset(digit, 0, sizeof(digit));
	length = b.length;
	for(int i = 0; i < length; i++){
		digit[i] = b.digit[i];
	}
	return *this;
}

bool BigInteger::operator<=(const BigInteger &b){
	if(length < b.length){
		return true;
	}else if(length > b.length){
		return false;
	}else{
		for(int i = length - 1; i >= 0; i--){
			if(digit[i] != b.digit[i]){
				return  digit[i] < b.digit[i];
			}
		}
	}
	return true;
}

bool BigInteger::operator==(const BigInteger &b){
	if(length != b.length){
		return false;
	}else{
		for(int i = length - 1; i >= 0; i--){
			if(digit[i] != b.digit[i]){
				return false;
			}
		}
	}
	return true;
}

BigInteger BigInteger::operator+(const BigInteger &b){
	BigInteger answer;
	int carry = 0;
	for(int i = 0; i < length || i < b.length; i++){
		int current = carry + digit[i] + b.digit[i];
		carry = current / 10;
		answer.digit[answer.length++] = current % 10;
	}
	if(carry != 0){
		answer.digit[answer.length++] = carry;
	}
	return answer;
}

BigInteger BigInteger::operator*(const BigInteger &b){
	BigInteger answer;
	answer.length = length + b.length;
	for(int i = 0; i < length; i++){
		for(int j = 0; j < b.length; j++){
			answer.digit[i + j] += digit[i] * b.digit[j];
		}
	}
	for(int i = 0; i < answer.length; i++){
		answer.digit[i + 1] += answer.digit[i] / 10;
		answer.digit[i] %= 10;
	}
	while(answer.length > 1 && answer.digit[answer.length - 1] == 0){
		answer.length--;
	}
	return answer;
}

//注意!!!只能返回正数,因此要在main函数中判断是大减小还是小减大
BigInteger BigInteger::operator-(const BigInteger &b){
	BigInteger answer;
	int carry = 0;
	for(int i = 0; i < length; i++){
		int current = digit[i] - b.digit[i] - carry;
		if(current < 0){
			current += 10;
			carry = 1;
		}else{
			carry = 0;
		}
		answer.digit[answer.length++] = current;
	}
	while(answer.length > 1 && answer.digit[answer.length - 1] == 0){
		answer.length--;
	}
	return answer;
}

BigInteger BigInteger::operator/(const BigInteger &b){
	BigInteger answer;
	answer.length = length;
	BigInteger remainder = 0;
	BigInteger tmp = b;
	//模拟列竖式进行除法运算的过程
	for(int i = length - 1; i >= 0; i--){
		if(!(remainder.length == 1 && remainder.digit[0] == 0)){
			for(int j = remainder.length - 1; j >= 0; j--){
				remainder.digit[j + 1] = remainder.digit[j];
			}
			remainder.length++;
		}
		remainder.digit[0] = digit[i];
		while(tmp <= remainder){
			remainder = remainder - tmp;
			answer.digit[i]++;
		}
	}
	while(answer.length > 1 && answer.digit[answer.length - 1] == 0){
		answer.length--;
	}
	return answer;
}

BigInteger BigInteger::operator%(const BigInteger &b){
	BigInteger remainder = 0;
	BigInteger tmp = b;
	for(int i = length - 1; i >= 0; i--){
		if(!(remainder.length == 1 && remainder.digit[0] == 0)){
			for(int j = remainder.length - 1; j >= 0; j--){
				remainder.digit[j + 1] = remainder.digit[j];
			}
			remainder.length++;
		}
		remainder.digit[0] = digit[i];
		while(tmp <= remainder){
			remainder = remainder - tmp;
		}
	}
	return remainder;
}

测试用例:

int main(){
	//测试整型方法
	int tmp1, tmp2;
	cout << "Input two positive Integer a and b:";
	cin >> tmp1 >> tmp2;
	BigInteger testInt1(tmp1), testInt2(tmp2);
	cout << "a.length = " << testInt1.length << ", b.length = " << testInt2.length << endl;
	cout << "a + b = " << testInt1 + testInt2 << endl;
	if(testInt1 <= testInt2 && !(testInt1 == testInt2)){
		cout << "a - b = " << "-" << testInt2 - testInt1 << endl;
	}else{
		cout << "a - b = " << testInt1 - testInt2 << endl;
	}
	cout << "a * b = " << testInt1 * testInt2 << endl;
	cout << "a / b = " << testInt1 / testInt2 << endl;
	cout << "a % b = " << testInt1 % testInt2 << endl;
	cout << "b + a = " << testInt2 + testInt1 << endl;
	if(testInt2 <= testInt1 && !(testInt1 == testInt2)){
		cout << "b - a = " << "-" << testInt1 - testInt2 << endl;
	}else{
		cout << "b - a = " << testInt2 - testInt1 << endl;
	}
	cout << "b * a = " << testInt2 * testInt1 << endl;
	cout << "b / a = " << testInt2 / testInt1 << endl;
	cout << "b % a = " << testInt2 % testInt1 << endl;
	if(testInt2 <= testInt1){
		cout << "b <= a ? yes" << endl;
	}else{
		cout << "b <= a ? no" << endl;
	}
	if(testInt2 == testInt1){
		cout << "b == a ? yes" << endl;
	}else{
		cout << "b == a ? no" << endl;
	}
	if(testInt1 <= testInt2){
		cout << "a <= b ? yes" << endl;
	}else{
		cout << "a <= b ? no" << endl;
	}
	BigInteger testInt3 = testInt1;
	if(testInt1 == testInt3){
		cout << "let c = a, and c == a ? yes" << endl;
	}else{
		cout << "let c = a, and c == a ? no" << endl;
	}
	//测试字符串大整数方法
	string strTmp1, strTmp2;
	cout << "Input two positive Integer a and b(a,b >= 10000000000000):";
	cin >> strTmp1 >> strTmp2;
	BigInteger s1(strTmp1), s2(strTmp2);
	cout << "a = " << s1 << ", length = " << s1.length 
		<< ", b = " << s2 << ", length = " << s2.length << endl;
	cout << "a + b = " << s1 + s2 << endl;
	if(s1 <= s2 && !(s1 == s2)){
		cout << "a - b = " << "-" << s2 - s1 << endl;
	}else{
		cout << "a - b = " << s1 - s2 << endl;
	}
	cout << "a * b = " << s1 * s2 << endl;
	cout << "a / b = " << s1 / s2 << endl;
	cout << "a % b = " << s1 % s2 << endl;
	cout << "b + a = " << s2 + s1 << endl;
	if(s1 <= s2 && !(s1 == s2)){
		cout << "b - a = " << s2 - s1 << endl;
	}else{
		cout << "b - a = " << "-" << s2 - s1 << endl;
	}
	cout << "b * a = " << s2 * s1 << endl;
	cout << "b / a = " << s2 / s1 << endl;
	cout << "b % a = " << s2 % s1 << endl;
	if(s2 <= s1){
		cout << "b <= a ? yes" << endl;
	}else{
		cout << "b <= a ? no" << endl;
	}
	if(s2 == s1){
		cout << "b == a ? yes" << endl;
	}else{
		cout << "b == a ? no" << endl;
	}
	if(s1 <= s2){
		cout << "a <= b ? yes" << endl;
	}else{
		cout << "a <= b ? no" << endl;
	}
	BigInteger s3 = s1;
	if(s1 == s3){
		cout << "let c = a, and c == a ? yes" << endl;
	}else{
		cout << "let c = a, and c == a ? no" << endl;
	}
	return 0;
}

测试用例:

  • int型BigInteger测试:12 7
  • string型BigInteger测试:12345678910234 10000000000000000000000000000000

结果截图:

2、快速幂

  • 定义:快速求得a的b次方的方法。
  • 任何一个数字n都可以分解为若干2的k次方之和。
  • 如求3的29次方,29 = 1 + 4 + 8 + 16,所以为3的1次方 * 3的4次方 * 3的8次方 * 3的16次方。
  • 乘积取模等于取模后再乘积,结果不变。(a * b) mod c = (a mod c) * (b mod c),如(4 * 2) mod 3 = 2 =  (4 mod 3) * (2 mod 3) = 1 * 2 = 2,(4 * 7) mod 3 = 1 =  (4 mod 3) * (7 mod 3) = 1 * 1 = 1。

3、矩阵与矩阵快速幂

  • 矩阵加法、矩阵乘法、矩阵转置等。
  • 矩阵快速幂:一种高效求矩阵多幂次的方法,类似于普通快速幂。对于数字快速幂而言,其初始值为1;对于矩阵快速幂而言,其初始值是单位矩阵。

二、应用实例

1、题目描述:求 a 的 b 次方对 p 取模的值,其中 0 ≤ a,b,p ≤10^9​。【牛客竞赛】

  • 输入格式:三个用空格隔开的整数a,b和p。
  • 输出格式:一个整数,表示 a^b mod p 的值。
  • 样例输入:
    • 2 3 9
  • 样例输出:
    • 8

示例代码:

#include <iostream>

using namespace std;

long long FastExponent(long long a, long long b, long long p){
	long long answer = 1 % p;
	while(b != 0){
		if(b % 2 == 1){
			answer *= a;
			answer %= p;
		}
		b /= 2;
		a *= a;
		a %= p;
	}
	return answer;
}

int main(){
	long long a, b, p;
	cin >> a >> b >> p;
	cout << FastExponent(a, b, p) << endl;
	return 0;
}

2、题目描述:N<k时,root(N,k) = N,否则,root(N,k) = root(N',k)。N'为N的k进制表示的各位数字之和。输入x,y,k,输出root(x^y,k)的值 (这里^为乘方,不是异或),2=<k<=16,0<x,y<2000000000,有一半的测试点里 x^y 会溢出int的范围(>=2000000000) 【清华大学】

  • 输入格式:每组测试数据包括一行,x(0<x<2000000000), y(0<y<2000000000), k(2<=k<=16)
  • 输出格式:输入可能有多组数据,对于每一组数据,root(x^y, k)的值
  • 样例输入:
    • 4 4 10
  • 样例输出:
    • 4

示例代码:

#include <iostream>

using namespace std;

long long FastExponent(long long x, long long y, long long k){
	long long answer = 1;
	while(y != 0){
		if(y % 2 == 1){
			answer = (answer * x) % k; //乘积取模等于取模后乘积,结果不变
		}
		y /= 2;
		x = (x * x) % k;
	}
	return answer;
}

int main(){
	long long x, y, k;
	while(cin >> x >> y >> k){
		long long result = FastExponent(x, y, k - 1);
		if(result == 0){
			cout << k - 1 << endl;
		}else{
			cout << FastExponent(x, y, k - 1) << endl;
		}
	}
	return 0;
}

附注:

(1)N = a0 +a1 * k^1 + a2 * k^2 + … + an * k^n;

N' = a0 + a1 + a2 + …+ an;

N - N' = a1 * (k^1 - 1) + a2 * (k^2 - 1) + … + an * (k^n - 1) = a1 * (k - 1) + a2 * (k - 1)(k + 1) + … + an * (k - 1)(k^(n - 1) + k^(n - 2) + … + k^2 + k^1 + 1) = (k - 1) * (提取的公因式);

(N - N') % (k - 1) = 0;

(N' - N'') % (k - 1) = 0;

……

(N'' - Nr) % (k - 1) = 0;

左右两式相加,得(N - Nr) % (k - 1) = 0;所以Nr = N % (k - 1)

3、题目描述:计算两个矩阵的乘积,第一个是2*3,第二个是3*2【哈尔滨工业大学】

  • 输入格式:输入为两个矩阵,其中一个为2*3的矩阵,另一个为3*2的矩阵
  • 输出格式:一个2*2的矩阵(每一个数字后都跟一个空格)
  • 样例输入:
    • 1 2 3
    • 3 4 5
    • 6 7
    • 8 9
    • 10 11
  • 样例输出:
    • 52 58
    • 100 112

示例代码:

#include <iostream>

using namespace std;

int arrayA[2][3];
int arrayB[3][2];
int result[2][2];

int main(){
	int number;
	//输入矩阵A
	for(int i = 0; i < 2; i++){
		for(int j = 0; j < 3; j++){
			cin >> number;
			arrayA[i][j] = number;
		}
	}
	//输入矩阵B
	for(int i = 0; i < 3; i++){
		for(int j = 0; j < 2; j++){
			cin >> number;
			arrayB[i][j] = number;
		}
	}
	for(int i = 0; i < 2; i++){
		for(int j = 0; j < 2; j++){
			result[i][j] = 0;
			for(int k = 0; k < 3; k++){
				result[i][j] += arrayA[i][k] * arrayB[k][j];
			}
		}
	}
	//输出结果矩阵
	for(int i = 0; i < 2; i++){
		for(int j = 0; j < 2; j++){
			cout << result[i][j] << " ";
		}
		cout << endl;
	}
	return 0;
}

4、题目描述:给定一个n*n的矩阵,求该矩阵的k次幂,即P^k。【北京邮电大学】

  • 输入格式:第一行:两个整数n(2<=n<=10)、k(1<=k<=5),两个数字之间用一个空格隔开,含义如上所示。
    接下来有n行,每行n个正整数,其中,第i行第j个整数表示矩阵中第i行第j列的矩阵元素Pij且(0<=Pij<=10)。另外,数据保证最后结果不会超过10^8。
  • 输出格式:对于每组测试数据,输出其结果。格式为:
    n行n列个整数,每行数之间用空格隔开,注意,每行最后一个数后面不应该有多余的空格。
  • 样例输入:
    • 3
    • 2 2
    • 9 8
    • 9 3
    • 3 3
    • 4 8 4
    • 9 3 0
    • 3 5 7
    • 5 2
    • 4 0 3 0 1
    • 0 0 5 8 5
    • 8 9 8 5 3
    • 9 6 1 7 8
    • 7 2 5 7 3
  • 样例输出:
    • 153 96
    • 108 81
    • 1216 1248 708
    • 1089 927 504
    • 1161 1151 739
    • 47 29 41 22 16
    • 147 103 73 116 94
    • 162 108 153 168 126
    • 163 67 112 158 122
    • 152 93 93 111 97

示例代码:

#include <iostream>

using namespace std;

const int MAXN = 10;

struct Matrix{
	int array[MAXN][MAXN];
	int row, column;
	Matrix(int row, int column):row(row), column(column){}
};

//矩阵乘法
Matrix MatrixMultiple(Matrix a, Matrix b){
	Matrix result(a.row, a.column);
	for(int i = 0; i < result.row; i++){
		for(int j = 0; j < result.column; j++){
			result.array[i][j] = 0;
			for(int k = 0; k < a.column; k++){
				result.array[i][j] += a.array[i][k] * b.array[k][j];
			}
		}
	}
	return result;
}

//构造单位矩阵
Matrix CreateUnitMatrix(int n){
	Matrix unitMatrix(n, n);
	for(int i = 0; i < unitMatrix.row; i++){
		for(int j = 0; j < unitMatrix.column; j++){
			if(i == j){
				unitMatrix.array[i][j] = 1;
			}else{
				unitMatrix.array[i][j] = 0;
			}
		}
	}
	return unitMatrix;
}

//矩阵快速幂
Matrix FastExpotentMatrix(Matrix a, int k){
	Matrix answer = CreateUnitMatrix(a.column);
	while(k != 0){
		if(k % 2 != 0){
			answer = MatrixMultiple(a, answer);
		}
		k /= 2;
		a = MatrixMultiple(a, a);
	}
	return answer;
}

int main(){
	int rowAndColumn, k;
	while(cin >> rowAndColumn >> k){
		Matrix matrix(rowAndColumn, rowAndColumn);
		int element;
		//输入矩阵
		for(int i = 0; i < matrix.row; i++){
			for(int j = 0; j < matrix.column; j++){
				cin >> element;
				matrix.array[i][j] = element;
			}
		}
		Matrix answer = FastExpotentMatrix(matrix, k);
		for(int i = 0; i < answer.row; i++){
			for(int j = 0; j < answer.column; j++){
				cout << answer.array[i][j] << " ";
			}
			cout << endl;
		}
	}
	return 0;
}

5、题目描述:This time, you are supposed to find A+B where A and B are two matrices, and then count the number of zero rows and columns.【浙江大学】

  • 输入格式:The input consists of several test cases, each starts with a pair of positive integers M and N (≤10) which are the number of rows and columns of the matrices, respectively. Then 2*M lines follow, each contains N integers in [-100, 100], separated by a space. The first M lines correspond to the elements of A and the second M lines to that of B.The input is terminated by a zero M and that case must NOT be processed.
  • 输出格式:For each test case you should output in one line the total number of zero rows and columns of A+B.
  • 样例输入:
    • 2 2
    • 1 1
    • 1 1
    • -1 -1
    • 10 9
    • 2 3
    • 1 2 3
    • 4 5 6
    • -1 -2 -3
    • -4 -5 -6
    • 0
  • 样例输出:
    • 1
    • 5

示例代码:

#include <iostream>

using namespace std;

const int MAX_N = 10;

struct Matrix{
	int a[MAX_N][MAX_N];
	int row, column;
	Matrix(int r, int c):row(r), column(c){}
};

Matrix CreateMatrix(int row, int column){
	int inputElement;
	Matrix matrix(row, column);
	for(int i = 0; i < matrix.row; i++){
		for(int j = 0; j < matrix.column; j++){
			cin >> inputElement;
			matrix.a[i][j] = inputElement;
		}
	}
	return matrix;
}

Matrix MatrixAdd(Matrix m1, Matrix m2){
	Matrix answer(m1.row, m1.column);
	for(int i = 0; i < m1.row; i++){
		for(int j = 0; j < m1.column; j++){
			answer.a[i][j] = m1.a[i][j] + m2.a[i][j];
		}
	}
	return answer;
}

int main(){
	int row, column;
	while(cin >> row && row != 0 && cin >> column){
		Matrix matrix1 = CreateMatrix(row, column), matrix2 = CreateMatrix(row, column);
		Matrix answer = MatrixAdd(matrix1, matrix2);
		int count = 0;
		for(int i = 0; i < answer.row; i++){
			int tmpCount = 0;
			for(int j = 0; j < answer.column; j++){
				tmpCount += answer.a[i][j];
			}
			if(tmpCount == 0){
				count++;
			}
		}
		for(int i = 0; i < answer.column; i++){
			int tmpCount = 0;
			for(int j = 0; j < answer.row; j++){
				tmpCount += answer.a[j][i];
			}
			if(tmpCount == 0){
				count++;
			}
		}
		cout << count << endl;
	}
	return 0;
}

6、题目描述:给定a0,a1,以及an=p*a(n-1) + q*a(n-2)中的p,q。这里n >= 2。 求第k个数对10000的模。【清华大学】

  • 输入格式:输入包括5个整数:a0、a1、p、q、k。
  • 输出格式:第k个数a(k)对10000的模。
  • 样例输入:
    • 20 1 1 14 5
  • 样例输出:
    • 8359

示例代码:

#include <iostream>
#include <vector>
#define MOD 10000
#define MAX_K 5000

using namespace std;

int answer[MAX_K]; 
int a0, a1, p, q, k;

int algorithm(int n, int answer[]){
	if(n == 0){
		return answer[0] = a0 % MOD;
	}else if(n == 1){
		return answer[1] = a1 % MOD;
	}else if(answer[n] != 0){
		return answer[n];
	}else{
		return answer[n] = ((p * algorithm(n - 1, answer)) % MOD 
			+ (q * algorithm(n - 2, answer)) % MOD) % MOD;
	}
}

int main(){
	cin >> a0 >> a1 >> p >> q >> k;
	cout << algorithm(k, answer) << endl;
	return 0;
}

7、题目描述:实现一个加法器,使其能够输出a+b的值。【华中科技大学】

  • 输入格式:输入包括两个数a和b,其中a和b的位数不超过1000位。
  • 输出格式:可能有多组测试数据,对于每组数据,输出a+b的值。
  • 样例输入:
    • 2 6
    • 10000000000000000000 10000000000000000000000000000000
  • 样例输出:
    • 8
    • 10000000000010000000000000000000

示例代码:

#include <iostream>
#include <string>
#include <cstring>

using namespace std;

const int MAXN = 1010;

struct BigInteger{
	int digit[MAXN];
	int length;
	BigInteger();
	BigInteger operator=(string str);
	BigInteger operator+(const BigInteger &b);
	template <class T>
	friend istream& operator>>(istream &in, BigInteger &x);
	template <class T>
	friend ostream& operator<<(ostream &out, const BigInteger &x);
};

BigInteger BigInteger::operator=(string str){
	memset(digit, 0, sizeof(digit));
	length = str.size();
	for(int i = 0; i < length; i++){
		digit[i] = str[length - 1 - i] - '0';
	}
	return *this;
}

BigInteger::BigInteger(){
	memset(digit, 0, sizeof(digit));
	length = 0;
}

BigInteger BigInteger::operator+(const BigInteger &b){
	BigInteger answer;
	int carry = 0;
	for(int i = 0; i < length || i < b.length; i++){
		int current = digit[i] + b.digit[i] + carry;
		carry = current / 10;
		answer.digit[answer.length++] = current % 10;
	}
	if(carry != 0){
		answer.digit[length++] = carry;
	}
	return answer;
}

istream& operator>>(istream &in, BigInteger &x){
	string str;
	in >> str;
	x = str;
	return in;
}

ostream& operator<<(ostream &out, const BigInteger &x){
	for(int i = x.length - 1; i >= 0; i--){
		out << x.digit[i];
	}
	return out;
}

int main(){
	BigInteger s1, s2;
	while(cin >> s1 >> s2){
		cout << s1 + s2 << endl;
	}
	return 0;
}

8、题目描述:输入一个正整数N,输出N的阶乘。【清华大学】

  • 输入格式:正整数N(0<=N<=1000)
  • 输出格式:输入可能包括多组数据,对于每一组输入数据,输出N的阶乘
  • 样例输入:
    • 4
    • 5
    • 15
  • 样例输出:
    • 24
    • 120
    • 1307674368000

示例代码:

#include <iostream>
#include <string>
#include <cstring>

using namespace std;

const int MAXN = 5000;

struct BigInteger{
	int digit[MAXN];
	int length;
	BigInteger();
	BigInteger(int x);
	BigInteger operator=(string str);
	BigInteger operator+(const BigInteger &b);
	BigInteger operator*(const BigInteger &b);
	template <class T>
	friend istream& operator>>(istream &in, BigInteger &x);
	template <class T>
	friend ostream& operator<<(ostream &out, const BigInteger &x);
};

BigInteger BigInteger::operator=(string str){
	memset(digit, 0, sizeof(digit));
	length = str.size();
	for(int i = 0; i < length; i++){
		digit[i] = str[length - 1 - i] - '0';
	}
	return *this;
}

BigInteger::BigInteger(){
	memset(digit, 0, sizeof(digit));
	length = 0;
}

BigInteger::BigInteger(int x){
	memset(digit, 0, sizeof(digit));
	length = 0;
	if(x == 0){
		digit[length++] = 0;
	}
	while(x != 0){
		digit[length++] = x % 10;
		x /= 10;
	}
}

BigInteger BigInteger::operator*(const BigInteger &b){
	BigInteger answer;
	answer.length = length + b.length;
	for(int i = 0; i < length; i++){
		for(int j = 0; j < b.length; j++){
			answer.digit[i + j] += digit[i] * b.digit[j];
		}
	}
	for(int i = 0; i < answer.length; i++){
		answer.digit[i + 1] += answer.digit[i] / 10;
		answer.digit[i] %= 10;
	}
	while(answer.length > 1 && answer.digit[answer.length - 1] == 0){
		answer.length--;
	}
	return answer;
}

istream& operator>>(istream &in, BigInteger &x){
	string str;
	in >> str;
	x = str;
	return in;
}

ostream& operator<<(ostream &out, const BigInteger &x){
	for(int i = x.length - 1; i >= 0; i--){
		out << x.digit[i];
	}
	return out;
}

int main(){
	int N;
	while(cin >> N){
		BigInteger answer(1);
		for(int i = 2; i <= N; i++){
			answer = answer * BigInteger(i);
		}
		cout << answer << endl;
	}
	return 0;
}

9、题目描述:给定a和n,计算a+aa+aaa+a...a(n个a)的和。【哈尔滨工业大学】

  • 输入格式:测试数据有多组,输入a,n(1<=a<=9,1<=n<=100)。
  • 输出格式:对于每组输入,请输出结果。
  • 样例输入:
    • 1 10
  • 样例输出:
    • 1234567900

示例代码:

#include <iostream>
#include <string>
#include <cstring>

using namespace std;

const int MAXN = 200;

struct BigInteger{
	int digit[MAXN];
	int length;
	BigInteger();
	BigInteger(string str);
	BigInteger operator=(string str);
	BigInteger operator+(const BigInteger &b);
	template <class T>
	friend istream& operator>>(istream &in, BigInteger &x);
	template <class T>
	friend ostream& operator<<(ostream &out, const BigInteger &x);
};

BigInteger BigInteger::operator=(string str){
	memset(digit, 0, sizeof(digit));
	length = str.size();
	for(int i = 0; i < length; i++){
		digit[i] = str[length - 1 - i] - '0';
	}
	return *this;
}

BigInteger BigInteger::operator+(const BigInteger &b){
	BigInteger answer;
	int carry = 0;
	for(int i = 0; i < length || i < b.length; i++){
		int current = digit[i] + b.digit[i] + carry;
		carry = current / 10;
		answer.digit[answer.length++] = current % 10;
	}
	if(carry != 0){
		answer.digit[answer.length++] = carry;
	}
	return answer;
}

BigInteger::BigInteger(){
	memset(digit, 0, sizeof(digit));
	length = 0;
}

BigInteger::BigInteger(string str){
	memset(digit, 0, sizeof(digit));
	length = str.size();
	for(int i = 0; i < length; i++){
		digit[i] = str[length - 1 - i] - '0';
	}
}

istream& operator>>(istream &in, BigInteger &x){
	string str;
	in >> str;
	x = str;
	return in;
}

ostream& operator<<(ostream &out, const BigInteger &x){
	for(int i = x.length - 1; i >= 0; i--){
		out << x.digit[i];
	}
	return out;
}

int main(){
	int a, n;
	while(cin >> a >> n){
		BigInteger answer("0");
		string s;
		for(int i = 1; i <= n; i++){
			s += '0' + a;
			answer = answer + BigInteger(s);
		}
		cout << answer << endl;
	}
	return 0;
}

10、题目描述:已知正整数k满足2<=k<=9,现给出长度最大为30位的十进制非负整数c,求所有能整除c的k。【北京大学】

  • 输入格式:若干个非负整数c,c的位数<=30。每行一个c。
  • 输出格式:每一个c的结果占一行,1) 若存在满足 c%k == 0 的k,输出所有这样的k,中间用空格隔开,最后一个k后面没有空格。2) 若没有这样的k则输出"none"。注意整数溢出问题,不要对-1进行计算。
  • 样例输入:
    • 30
    • 72
    • 13
    • -1
  • 样例输出:
    • 2 3 5 6
    • 2 3 4 6 8 9
    • none

示例代码:

#include <iostream>
#include <string>
#include <cstring>

using namespace std;

const int MAXN = 200;

struct BigInteger{
	int digit[MAXN];
	int length;
	BigInteger();
	BigInteger(string str);
	BigInteger(int x);
	BigInteger operator=(string str);
	BigInteger operator=(const BigInteger &b);
	BigInteger operator-(const BigInteger &b);
	BigInteger operator%(const BigInteger &b);
	bool operator<=(const BigInteger &b);
};

BigInteger BigInteger::operator=(string str){
	memset(digit, 0, sizeof(digit));
	length = str.size();
	for(int i = 0; i < length; i++){
		digit[i] = str[length - 1 - i] - '0';
	}
	return *this;
}

bool BigInteger::operator<=(const BigInteger &b){
	if(length < b.length){
		return true;
	}else if(length > b.length){
		return false;
	}else{
		for(int i = length - 1; i >= 0; i--){
			if(digit[i] > b.digit[i]){
				return false;
			}
		}
	}
	return true;
}

BigInteger BigInteger::operator-(const BigInteger &b){
	BigInteger answer;
	int carry = 0;
	for(int i = 0; i < length; i++){
		int current = digit[i] - b.digit[i] - carry;
		if(current < 0){
			current += 10;
			carry = 1;
		}else{
			carry = 0;
		}
		answer.digit[answer.length++] = current;
	}
	while(answer.length > 1 && answer.digit[answer.length - 1] == 0){
		answer.length--;
	}
	return answer;
}

BigInteger BigInteger::operator%(const BigInteger &b){
	BigInteger remainder("0");
	BigInteger tmp = b;
	for(int i = length - 1; i >= 0; i--){
		if(!(remainder.length == 1 && remainder.digit[0] == 0)){
			for(int j = remainder.length - 1; j >= 0; j--){
				remainder.digit[j + 1] = remainder.digit[j];
			}
			remainder.length++;
		}
		remainder.digit[0] = digit[i];
		while(tmp <= remainder){
			remainder = remainder - tmp;
		}
	}
	return remainder;
}

BigInteger::BigInteger(){
	memset(digit, 0, sizeof(digit));
	length = 0;
}

BigInteger::BigInteger(string str){
	memset(digit, 0, sizeof(digit));
	length = str.size();
	for(int i = 0; i < length; i++){
		digit[i] = str[length - 1 - i] - '0';
	}
}

BigInteger::BigInteger(int x){
	memset(digit, 0, sizeof(digit));
	length = 0;
	if(x == 0){
		digit[length++] = 0;
	}
	while(x != 0){
		digit[length++] = x % 10;
		x /= 10;
	}
}

BigInteger BigInteger::operator=(const BigInteger &b){
	memset(digit, 0, sizeof(digit));
	length = b.length;
	for(int i = 0; i < length; i++){
		digit[i] = b.digit[i];
	}
	return *this;
}

int main(){
	string str;
	while(cin >> str && str != "-1"){
		BigInteger input(str), answer, tmp;
		bool flag = false;
		for(int k = 2; k <= 9; k++){
			tmp = k;
			answer = input % tmp;
			if(answer.length == 1 && answer.digit[0] == 0){
				cout << k << " ";
				flag = true;
			}
		}
		if(!flag){
			cout << "none";
		}
		cout << endl;
	}
	return 0;
}

参考文献:

[1]杨泽邦、赵霖. 计算机考研——机试指南(第2版). [M]北京:电子工业出版社,2019.11;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值