1 介绍
本博客用来记录筛质数、分解质因数和快速幂相关的题目。
2 训练
题目1:1292哥德巴赫猜想
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;
}
题目2:1293夏洛克和他的女朋友
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;
}
题目3:196质数距离
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;
}
题目4:197阶乘分解
解题思路:
结论: 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!=1⋅2⋅3⋯n,这 n n n个数中,
- 存在因数 x x x的数的个数为: n x \frac{n}{x} xn
- 存在因数 x 2 x^2 x2的数的个数为: n x 2 \frac{n}{x^2} x2n
- 存在因数 x 3 x^3 x3的数的个数为: n x 3 \frac{n}{x^3} x3n
- ……
将上述各项相加,即为 n ! n! n!中质因数 x x x的个数。
-------------------------------------------------举例开始-------------------------------------------------
我们要求解 10 ! 10! 10!中质因数 3 3 3的出现次数,
- 存在因数 3 3 3的数的个数为: 10 3 = 3 \frac{10}{3}=3 310=3,分别是3、6、9这三个数。
- 存在因数 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;
}
题目5:1289序列的第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;
}
题目6:1290越狱
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;
}