《王道論壇考研機試指南》第三章【數論】
阿新 • • 發佈:2019-02-15
數位拆解
#include <cstdio>
using namespace std;
int main() {
int a, b; // 儲存兩個整數的變數
while (scanf("%d%d", &a, &b) != EOF) {
int buf1[20], buf2[20], size1 = 0, size2 = 0;
while (a != 0) {
buf1[size1++] = a % 10 ;
a /= 10;
}
while (b != 0) {
buf2[size2++] = b % 10;
b /= 10;
}
int ans = 0;
for (int i = 0; i < size1; i++) {
for (int j = 0; j < size2; j++)
ans += buf1[i] * buf2[j];
}
printf("%d\n" , ans);
}
return 0;
}
#include <cstdio>
using namespace std;
int main() {
char a[11], b[11];
while (scanf("%s%s", a, b) != EOF) {
int ans = 0;
for (int i = 0; a[i] != 0; i++) {
for (int j = 0; b[j] != 0; j++)
ans += (a[i] - '0') * (b[j] - '0' );
}
printf("%d\n", ans);
}
return 0;
}
進位制轉換
#include <cstdio>
int main() {
long long a, b;
int m;
while (scanf("%d", &m) != EOF) {
if (m == 0)
break;
scanf("%lld%lld", &a, &b);
a = a + b;
int ans[50], size = 0;
ans[size++] = a % m;
a = a/m;
while (a != 0) {
ans[size++] = a % m;
a = a/m;
}
for (int i = size-1; i >= 0; i--) {
printf("%d", ans[i]);
}
printf("\n");
}
return 0;
}
數制轉換
#include <cstdio>
#include <cstring>
int main() {
int a, b;
char str[40];
while (scanf("%d%s%d", &a, str, &b) != EOF) {
// tmp為我們將要計算的a進位制對應的十進位制數,length為字串長度方便我們從低到高位遍歷每個數位上的數
// c為各個數位的權重,初始化為1,表示最低位數位權為1,之後每位權重都是前一位權重的a倍
int tmp = 0, length = strlen(str), c = 1;
for (int i = length-1; i >= 0; i--) {
int x;
if (str[i] >= '0' && str[i] <= '9')
x = str[i] - '0'; // 當字元在0到9之間,計算其代表的數字
else if (str[i] >= 'a' && str[i] <= 'z')
x = str[i] - 'a' + 10;
else
x = str[i] - 'A' + 10;
tmp += x * c;
c *= a;
}
char ans[40], size = 0;
int x = tmp % b;
ans[size++] = (x < 10) ? x+'0' : x-10+'A';
tmp /= b;
while (tmp != 0) {
x = tmp % b;
ans[size++] = (x < 10) ? x+'0' : x-10+'A';
tmp /= b;
}
for (int i = size-1; i >= 0; i--)
printf("%c", ans[i]);
printf("\n");
}
return 0;
}
最大公約數
#include <cstdio>
int gcd(int a, int b){
if (b == 0)
return a;
else
return gcd(b, a%b);
}
int main() {
int a, b;
while (scanf("%d%d", &a, &b) != EOF) {
printf("%d\n", gcd(a, b));
}
return 0;
}
最小公倍數
#include <cstdio>
int gcd(int a, int b) {
int tmp;
while (b != 0) {
tmp = a % b;
a = b;
b = tmp;
}
return a;
}
int main() {
int a, b;
while (scanf("%d%d", &a, &b) != EOF) {
printf("%d\n", a*b/gcd(a, b));
}
return 0;
}
素數篩法
#include <cstdio>
#include <cmath>
bool judge(int x) {
if (x <= 1)
return false;
int bound = (int)sqrt(x)+1;
for (int i = 2; i < bound; i++) {
if (x % i == 0)
return false;
}
return true;
}
int main() {
int x;
while (scanf("%d", &x) != EOF) {
if (judge(x))
printf("yes\n");
else
printf("no\n");
}
return 0;
}
分解素因數
#include <cstdio>
int prime[10000]; // 儲存篩得的素數
int primeSize; // 儲存素數個數
bool mark[10001]; // 若mark[x]為true,則表示該數x已被標註為非素數
void init() {
for (int i = 1; i <= 10000; i++)
mark[i] = false;
primeSize = 0;
for (int i = 2; i <= 10000; i++) {
if (mark[i] == true)
continue;
prime[primeSize++] = i;
for (int j = i*i; j <= 10000; j += i)
mark[j] = true;
}
}
int main() {
init();
int n;
while (scanf("%d", &n) != EOF) {
int ansPrime[30];
int ansSize = 0;
int ansNum[30];
for (int i = 0; i < primeSize; i++) {
if (n % prime[i] == 0) {
ansPrime[ansSize] = prime[i];
ansNum[ansSize] = 0;
while (n % prime[i] == 0) {
ansNum[ansSize]++;
n /= prime[i];
}
ansSize++;
if (n == 1)
break;
}
}
if (n != 1) {
ansPrime[ansSize] = n;
ansNum[ansSize++] = 1;
}
int ans = 0;
for (int i = 0; i < ansSize; i++)
ans += ansNum[i];
printf("%d\n", ans);
}
return 0;
}
#include <iostream>
#include <cstdio>
bool mark[1010];
int prime[1010];
int primeSize;
void init() {
primeSize = 0;
for (int i = 2; i <= 1000; i++) {
if (mark[i] == true)
continue;
prime[primeSize++] = i;
for (int j = i*i; j <= 1000; j += i)
mark[j] = true;
}
}
int cnt[1010]; // cnt[i]用來表示prime[i]所儲存的素數在n!中的因子數,即n!分解因數後,素因子prime[i]所對應的冪指數,可能為0
int cnt2[1010]; // cnt[i]用來表示prime[i]所儲存的素數在a中的因子數
int main() {
int n, a;
init();
while (scanf("%d%d", &n, &a) == 2) {
for (int i = 0; i < primeSize; i++) {
cnt[i] = cnt[2] = 0;
}
for (int i = 0; i < primeSize; i++) {
int t = n; // 用臨時變數儲存n的值
while (t) {
cnt[i] += t/prime[i];
t = t/prime[i];
} // 依次計算t/prime[i]^k,直到t/prime[i]^k變為0
}
int ans = 123123123;
for (int i = 0; i < primeSize; i++) {
while (a%prime[i] == 0) {
cnt2[i]++;
a /= prime[i];
} // 計算a中素因數prime[i]對應的冪指數
if (cnt2[i] == 0)
continue;
if (cnt[1]/cnt[2] < ans)
ans = cnt[i] / cnt2[i]; // 統計這些商的最小值
}
printf("%d\n", ans);
}
return 0;
}
二分求冪
#include <cstdio>
int main() {
int a, b;
while (scanf("%d%d", &a, &b) != EOF) {
if (a == 0 && b == 0)
break;
int ans = 1;
while (b != 0) {
if (b % 2 == 1) {
ans *= a;
ans %= 1000;
}
b /= 2;
a *= a;
a %= 1000;
}
printf("%d\n", ans);
}
return 0;
}
高精度整數
struct bigInteger {
int digit[1000];
int size;
};
#include <cstdio>
#include <cstring>
struct bigInteger { // 高精度整數結構體
int digit[1000]; // 按四位數一個單位儲存數值
int size; // 下一個我們未使用的陣列單元
void init() {
for (int i = 0; i < 1000; i++)
digit[i] = 0;
size = 0;
}
void set(char str[]) { // 從字串中提取整數
init();
int L = strlen(str);
for (int i = L-1, j = 0, t = 0, c = 1; i >= 0; i--) {
// 從最後一個字元開始倒序遍歷字串,j控制每4個字元轉換為一個數字存入陣列
// t臨時儲存字元轉換為數字的中間值,c表示當前位置的權重,按1,10,100,1000順序變化
t += (str[i] - '0') * c; // 計算這個四位數中當前字元代表的數字,即數字乘以當前位的權重
j++; // 當前轉換字元數增加
c *= 10;
if (j == 4 || i== 0) {
digit[size++] = t;
j = 0;
t = 0;
c = 1;
}
}
}
void output() {
for (int i = size-1; i >= 0; i--) {
if (i != size-1)
printf("%04d", digit[i]); // 若當前輸出的不是最高位數字,用%04輸出前導0,即當前數字不足4位時由0補充,如輸出110001的後四位數
else
printf("%d", digit[i]);
}
printf("\n");
}
bigInteger operator + (const bigInteger &A) const { // 加法運算子
bigInteger ret; // 返回值,即兩數相加的結果
ret.init(); // 對其初始化
int carry = 0; // 進位,初始值為0
for (int i = 0; i < A.size || i < size; i++) {
int tmp = A.digit[i] + digit[i] + carry; // 計算兩個整數當前位以及來自低位的進位和
carry = tmp / 10000; // 計算該位的進位
tmp %= 10000; // 去除進位部分,取後四位
ret.digit[ret.size++] = tmp;
}
if (carry != 0) { // 計算結果後若最高位有進位
ret.digit[ret.size++] = carry; // 儲存該進位
}
return ret;
}
}a, b, c;
char str1[1002], str2[1002];
int main() {
while (scanf("%s%s", str1, str2) != EOF) {
a.set(str1);
b.set(str2);
c = a + b;
c.output();
}
return 0;
}
#include <cstdio>
#include <cstring>
struct bigInteger { // 高精度整數結構體
int digit[1000]; // 按四位數一個單位儲存數值
int size; // 下一個我們未使用的陣列單元
void init() {
for (int i = 0; i < 1000; i++)
digit[i] = 0;
size = 0;
}
void set(int x) {
init();
digit[size++] = x % 10000;
x /= 10000;
while (x != 0) {
digit[size++] = x % 10000;
x /= 10000;
}
}
void output() {
for (int i = size-1; i >= 0; i--) {
if (i != size-1)
printf("%04d", digit[i]); // 若當前輸出的不是最高位數字,用%04輸出前導0,即當前數字不足4位時由0補充,如輸出110001的後四位數
else
printf("%d", digit[i]);
}
printf("\n");
}
bigInteger operator * (int x) const { // 乘法運算子
bigInteger ret; // 將要返回的高精度整數
ret.init(); // 對其初始化
int carry = 0; // 進位,初始值為0
for (int i = 0; i < size; i++) {
int tmp = x * digit[i] + carry; // 用小整數x乘以當前位數字並加上來自低位的進位
carry = tmp / 10000; // 計算該位的進位
tmp %= 10000; // 去除進位部分,取後四位
ret.digit[ret.size++] = tmp;
}
if (carry != 0) { // 計算結果後若最高位有進位
ret.digit[ret.size++] = carry; // 儲存該進位
}
return ret;
}
}a;
int main() {
int n;
while (scanf("%d", &n) != EOF) {
a.init();
a.set(1);
for (int i = 1; i <= n; i++) {
a = a * i; // 依次乘上每一個數
}
a.output();
}
return 0;
}
進位制轉換
#include <cstdio>
#include <cstring>
#define maxDigits 100
struct bigInteger { // 高精度整數結構體
int digit[maxDigits]; // 按四位數一個單位儲存數值
int size; // 下一個我們未使用的陣列單元
void init() {
for (int i = 0; i < maxDigits; i++)
digit[i] = 0;
size = 0;
}
void set(int x) {
init();
digit[size++] = x % 10000;
x /= 10000;
while (x != 0) {
digit[size++] = x % 10000;
x /= 10000;
}
}
void output() {
for (int i = size-1; i >= 0; i--) {
if (i != size-1)
printf("%04d", digit[i]); // 若當前輸出的不是最高位數字,用%04輸出前導0,即當前數字不足4位時由0補充,如輸出110001的後四位數
else
printf("%d", digit[i]);
}
printf("\n");
}
bigInteger operator * (int x) const { // 高精度整數與普通整數的乘積
bigInteger ret;
ret.init();
int carry = 0;
for (int i = 0; i < size; i++) {
int tmp = x * digit[i] + carry;
carry = tmp / 10000;
tmp %= 10000;
ret.digit[ret.size++] = tmp;
}
if (carry != 0) {
ret.digit[ret.size++] = carry;
}
return ret;
}
bigInteger operator + (const bigInteger &A) const { // 高精度整數之間的加法運算
bigInteger ret;
ret.init();
int carry = 0;
for (int i = 0; i < A.size || i < size; i++) {
int tmp = A.digit[i] + digit[i] + carry;
carry = tmp / 10000;
tmp %= 10000;
ret.digit[ret.size++] = tmp;
}
if (carry != 0) {
ret.digit[ret.size++] = carry;
}
return ret;
}
bigInteger operator / (int x) const { // 高精度整數除以普通整數
bigInteger ret;
ret.init();
int remainder = 0; // 餘數
for (int i = size-1; i >= 0; i--) { // 從最高位至最低位依次完成計算
int t = (remainder*10000 + digit[i]) / x; // 計算當前位置數值加上高位剩餘的餘數的和對x求得的商
int r = (remainder*10000 + digit[i]) % x; // 計算當前數位值加上搞衛生與的餘數的和對x求模後的餘數
ret.digit[i] = t; // 儲存本位的值
remainder = r; // 儲存至本位為止的餘數
}
ret.size = 0; // 返回高精度整數的size初始值為0,即當前所有位數字都為0時,digit[0]代表數字0,作為最高有效位,高精度整數即為數字0
for (int i = 0; i < maxDigits; i++) {
if (digit[i] != 0)
ret.size = i;
} // 若存在非0位,確定最高的非0位,作為最高有效位
ret.size++; // 最高有效位的下一位即為下一個我們不曾使用的digit陣列單元,確定為size的值
return ret;
}
int operator % (int x) const { // 高精度整數對普通整數求餘數
int remainder = 0; // 餘數
for (int i = size-1; i >= 0; i--) {
int t = (remainder*10000 + digit[i]) / x;
int r = (remainder*10000 + digit[i]) % x;
remainder = r;
} // 過程同高精度整數對普通整數求商
return remainder; // 返回餘數
}
}a, b, c;
char str[10000];
char ans[10000];
int main() {
int n, m;
while (scanf("%d%d", &m, &n) != EOF) {
scanf("%s", str); // 輸入m進位制數
int L = strlen(str);
a.set(0); // a的初始值為0,用來儲存轉換成十進位制的m進位制數
b.set(1); // b的初始值為1,在m進位制向十進位制轉換的過程中,依次代表每一位的權重
for (int i = L-1; i >= 0; i--) { // 由低位至高位轉換m進位制數至相應的十進位制數
int t;
if (str[i] >= '0' && str[i] <= '9') {
t = str[i] - '0';
} else
t = str[i] - 'A' + 10; // 確定當前位字元代表的數字
a = a+b*t; // 累加當前數字乘當前位權重的積
b = b*m; // 計算下一位權重
}
int size = 0; // 代表轉換為n進位制後的字元個數
do { // 對轉換後的十進位制數求其n進位制值
int t = a % n; // 求餘數
if (t >= 10)
ans[size++] = t-10+'a';
else ans[size++] = t+'0'; // 確定當前位字元
a = a / n; // 求商
} while (a.digit[0] != 0 || a.size != 1); // 當a不為0時重複該過程
for (int i = size-1; i >= 0; i--)
printf("%c", ans[i]);
printf("\n");
}
return 0;
}