acwing算法提高之数学知识--筛质数、分解质因数和快速幂

123 篇文章 1 订阅

1 介绍

本博客用来记录筛质数、分解质因数和快速幂相关的题目。

2 训练

题目11292哥德巴赫猜想

C++代码如下,

#include <iostream>
#include <cstring>
#include <algorithm>
#include <set>

using namespace std;

const int N = 1e6 + 10;

set<int> s;

//处理出N以内的所有奇质数
void init() {
    vector<bool> st(N, false);
    vector<int> primes;
    for (int i = 2; i < N; ++i) {
        if (!st[i]) primes.emplace_back(i);
        for (int j = 0; primes[j] <= N / i; ++j) {
            st[primes[j] * i] = true;
            if (i % primes[j] == 0) break; 
        }
    }
    
    for (auto x : primes) {
        if (x % 2 == 1) s.insert(x);
    }
    
    return;
}

int main() {
    init();
    
    int x;
    while (cin >> x, x) {
        auto iter = s.lower_bound(x);
        bool flag = true;
        while (true) {
            int a = *iter;
            //cout << a << endl;
            int b = x - a;
            if (s.count(b)) {
                printf("%d = %d + %d\n", x, b, a);
                flag = false;
                break;
            }
            
            if (iter == s.begin()) break;
            
            iter--;
        }
        
        if (flag) {
            printf("Goldbach's conjecture is wrong.");
        }
    }
    
    return 0;
}

题目21293夏洛克和他的女朋友

C++代码如下,

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>

using namespace std;

const int N = 1000010;

int primes[N], cnt;
bool st[N];

void init(int n) {
    for (int i = 2; i <= n; ++i) {
        if (!st[i]) primes[cnt++] = i;
        for (int j = 0; primes[j] <= n / i; ++j) {
            st[i * primes[j]] = true;
            if (i % primes[j] == 0) break;
        }
    }
}

int main() {
    int n;
    cin >> n;
    
    init(n + 1);
    
    if (n <= 2) puts("1");
    else puts("2");
    
    for (int i = 2; i <= n + 1; ++i) {
        if (!st[i]) printf("1 ");
        else printf("2 ");
    }
    
    return 0;
}

题目3196质数距离

C++代码如下,

#include <iostream>
#include <cstring>
#include <algorithm>

using namespace std;

typedef long long LL;

const int N = 1000010;

int primes[N], cnt;
bool st[N];

void init(int n) {
    memset(st, 0, sizeof st);
    cnt = 0;
    for (int i = 2; i <= n; ++i) {
        if (!st[i]) primes[cnt++] = i;
        for (int j = 0; primes[j] * i <= n; j++) {
            st[i * primes[j]] = true;
            if (i % primes[j] == 0) break;
        }
    }
}

int main() {
    int l, r;
    while (cin >> l >> r) {
        init(50000);
        
        memset(st, 0, sizeof st);
        for (int i = 0; i < cnt; ++i) {
            LL p = primes[i];
            for (LL j = max(p * 2, (l + p - 1) / p * p); j <= r; j += p) {
                st[j - l ] = true;
            }
        }
        
        cnt = 0;
        for (int i = 0; i <= r - l; ++i) {
            if (!st[i] && i + l >= 2) {
                primes[cnt++] = i + l;
            }
        }
        
        if (cnt < 2) puts("There are no adjacent primes.");
        else {
            int minp = 0, maxp = 0;
            for (int i = 0; i + 1 < cnt; ++i) {
                int d = primes[i+1] - primes[i];
                if (d < primes[minp+1] - primes[minp]) minp = i;
                if (d > primes[maxp+1] - primes[maxp]) maxp = i;
            }
            
            printf("%d,%d are closest, %d,%d are most distant.\n",
                primes[minp], primes[minp+1],
                primes[maxp], primes[maxp+1]);
        }
    }
    
    return 0;
}

题目4197阶乘分解

解题思路:

结论: n ! n! n!中质因数 x x x的个数为 n x + n x 2 + ⋯ + n x + ∞ \frac{n}{x}+\frac{n}{x^2}+\cdots+\frac{n}{x^{+\infin}} xn+x2n++x+n

推理如下,

n ! = 1 ⋅ 2 ⋅ 3 ⋯ n n!=1\cdot2\cdot 3\cdots n n!=123n,这 n n n个数中,

  1. 存在因数 x x x的数的个数为: n x \frac{n}{x} xn
  2. 存在因数 x 2 x^2 x2的数的个数为: n x 2 \frac{n}{x^2} x2n
  3. 存在因数 x 3 x^3 x3的数的个数为: n x 3 \frac{n}{x^3} x3n
  4. ……

将上述各项相加,即为 n ! n! n!中质因数 x x x的个数。

-------------------------------------------------举例开始-------------------------------------------------

我们要求解 10 ! 10! 10!中质因数 3 3 3的出现次数,

  1. 存在因数 3 3 3的数的个数为: 10 3 = 3 \frac{10}{3}=3 310=3,分别是3、6、9这三个数。
  2. 存在因数 3 2 = 9 3^2=9 32=9的数的个数为: 10 9 = 1 \frac{10}{9}=1 910=1,分别为9这个数。

那么 10 ! 10! 10!中质因数3的出现次数为 3 + 1 = 4 3+1=4 3+1=4

-------------------------------------------------举例结束-------------------------------------------------

因此,我们可以预先处理出n以内的质数,然后求这些质数在n!中的出现次数,也即指数。

C++代码如下,

#include <bits/stdc++.h>

using namespace std;

int main() {
    int n;
    cin >> n;
    
    vector<int> primes;
    vector<int> st(n + 1, false);
    for (int i = 2; i <= n; ++i) {
        if (!st[i]) primes.emplace_back(i);
        for (auto prime : primes) {
            if (i * prime > n) break;
            st[i*prime] = true;
            if (i % prime == 0) break;
        }
    }
    
    for (auto prime : primes) {
        int cnt = 0;
        for (int j = n; j > 0; j /= prime) {
            cnt += j / prime;
        }
        cout << prime << " " << cnt << endl;
    }
    
    return 0;
}

题目51289序列的第k个数

C++代码如下,

#include <iostream>
#include <cstring>
#include <algorithm>

using namespace std;

typedef long long LL;

const int mod = 200907;

int qmi(int a, int k, int p) {
    LL res = 1;
    while (k) {
        if (k & 1) res = (LL)res * a % p;
        k >>= 1;
        a = (LL)a * a % p;
    }
    return res;
}

int main() {
    int T;
    cin >> T;
    while (T--) {
        int a, b, c, k;
        cin >> a >> b >> c >> k;
        if (a + c == 2 * b) {
            //等差数列
            long long d = b - a;
            int res = ((LL)a + (LL)(k - 1) * d % mod) % mod;
            cout << res << endl;
        } else {
            //等比数列
            int q = b / a;
            int res = (LL)qmi(q, k-1, mod) * (LL)(a % mod) % mod;
            cout << res << endl;
        }
    }
    return 0;
}

题目61290越狱

C++代码如下,

#include <iostream>
#include <cstring>
#include <algorithm>

using namespace std;

typedef long long LL;

const int mod = 100003;

int qmi(int a, LL k, int p) {
    LL res = 1;
    while (k) {
        if (k & 1) res = (LL)res * a % p;
        k >>= 1;
        a = (LL)a * a % p;
    }
    return res;
}

int main() {
    int m;
    LL n;
    cin >> m >> n;
    
    LL a = qmi(m, n, mod);
    LL b = qmi(m-1, n-1, mod);
    b = m * b % mod;
    LL res = (a - b + mod) % mod;
    cout << res << endl;
    
    return 0;
}
  • 7
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

YMWM_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值