机试编程(五)——数学问题(二)
目录:
- 基础知识
- 大整数运算
- 快速幂
- 矩阵与矩阵快速幂
- 应用实例
- a^b【牛客竞赛】
- 求root(N, k)【清华大学】
- 计算两个矩阵的乘积【哈尔滨工业大学】
- 矩阵幂【北京邮电大学】
- A+B for Matrices【浙江大学】
- 递推数列【清华大学】
- 大整数运算:a+b【华中科技大学】
- N的阶乘【清华大学】
- 数字阶梯求和【哈尔滨工业大学】
- 大整数的因子【北京大学】
一、基础知识
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;