《王道论坛考研机试指南》第三章【数论】

数位拆解

特殊除法

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

进制转换

又一版A+B

#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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值