1. 程式人生 > >《王道論壇考研機試指南》第三章【數論】

《王道論壇考研機試指南》第三章【數論】

數位拆解

特殊除法

#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;
};

a+b

#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;
}

N的階乘

#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;
}