欧拉计划 41~50
41
思考一下可以发现,各数位之和 \(\sum\limits_{i = 1}^n i = \frac{n(n + 1)}{2}\),当 \(n = 2, \, 3, \, 5, \, 6, \, 8, \, 9\) 均为 \(3\) 的倍数,我们直接考虑搜索 \(7\) 位数的数字即可,可以筛表,我使用 python 简单化操作,利用 itertools
库中的 permutations
函数实现全排列。
# python
from sympy import *
import itertools
num = "1234567"
Num = itertools.permutations(num)
ans = 0
for i in Num:
if isprime(int("".join(i))):
ans = max(ans, int("".join(i)))
print(ans)
42
简单模拟
from sympy import *
is_sqr = [0 for _ in range(1000)]
for i in range(40):
is_sqr[i * (i + 1) // 2] = 1
words = ["word.txt"]
ans = 0
for word in words:
cnt = 0
for s in word:
cnt += ord(s) - ord('A') + 1
ans += is_sqr[cnt]
print(ans)
43
from sympy import *
from itertools import *
S = "0123456789"
lis = permutations(S)
primes = [2, 3, 5, 7, 11, 13, 17]
ans = 0
for num in lis:
flag = 0
num = "".join(num)
for i in range(7):
if int(num[i + 1 : i + 4]) % primes[i] > 0:
flag = 1
if not flag: ans += int(num)
print(ans)
44
逐个加入五边形数,如果他们的差存在,我们就给他们的和打上标记,如果加入的五边形数被标记了,说明已经存在一对五边形数他们的和差都是五边形数,虽然不一定找到第一个值就是最小的,但是答案确实满足这个条件,如果不放心可以多算几组取 \(\min\) 也是一样的。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
vector<ll> P;
unordered_map<ll, ll> mp, exist;
int main() {
for (ll i = 1; i; i ++ ) {
ll now = i * (3 * i - 1) / 2;
for (auto t : P) {
if (exist.count(now - t)) {
mp[now + t] = now - t;
}
}
exist[now] = 1;
P.push_back(now);
if (mp.count(now)) return cout << mp[now] << "\n", 0;
}
return 0;
}
45
三指针,让这个东西单调,很快就能出答案。
#include<bits/stdc++.h>
using namespace std;
#define ll long long
ll p1(ll x) {return x * (x + 1) / 2;}
ll p2(ll x) {return x * (3 * x - 1) / 2;}
ll p3(ll x) {return x * (2 * x - 1);}
int main() {
int t1 = 286, t2 = 166, t3 = 144;
while (p1(t1) != p2(t2) || p2(t2) != p3(t3)) {
if (p1(t1) < p2(t2)) t1 ++ ;
if (p1(t1) > p2(t2)) t2 ++ ;
if (p3(t3) < p2(t2)) t3 ++ ;
if (p3(t3) > p2(t2)) t2 ++ ;
}
cout << p1(t1) << "\n";
return 0;
}
46
筛除素数表然后逐个判断即可,实际发现答案很小。
// cpp
#include<bits/stdc++.h>
using namespace std;
const int N = 1e6 + 10;
int primes[N], st[N], cnt;
int is[N];
int main() {
st[1] = 1;
for (int i = 2; i < N; i ++ ) {
if (!st[i]) primes[cnt ++ ] = i;
for (int j = 0; i * primes[j] < N; j ++ ) {
st[i * primes[j]] = 1;
if (i % primes[j] == 0) break;
}
}
for (int i = 9; i < N; i += 2) {
if (!st[i]) continue;
int flag = 0;
for (int j = 1; j * j * 2 < i; j ++ ) {
if (!st[i - j * j * 2]) {
flag = 1;
break;
}
}
if (!flag) {
cout << i << "\n";
break;
}
}
return 0;
}
47
筛素数之后用素数表分解即可。
// cpp
#include<bits/stdc++.h>
using namespace std;
const int N = 1e6 + 10;
int primes[N], st[N], cnt;
int is[N];
int main() {
st[1] = 1;
for (int i = 2; i < N; i ++ ) {
if (!st[i]) primes[cnt ++ ] = i;
for (int j = 0; i * primes[j] < N; j ++ ) {
st[i * primes[j]] = 1;
if (i % primes[j] == 0) break;
}
}
int flag = 0;
for (int x = 2; x < N; x ++ ) {
int t = x, cnt = 0;
for (int j = 0; primes[j] * primes[j] <= t; j ++ ) {
if (t % primes[j] == 0) {
cnt ++ ;
while (t % primes[j] == 0) t /= primes[j];
}
}
if (t > 1) cnt ++ ;
if (cnt == 4) flag ++ ;
else flag = 0;
if (flag == 4) {
cout << x - 3 << "\n";
break;
}
}
return 0;
}
48
一个快速幂的板子题,唯一要注意的是由于模数是 \(10^{10}\),因此我们需要用 int128
来存储,如果是 python
,就不用在意。
// cpp
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const ll mod = 1e10;
ll qpow(__int128 a, ll k) {
__int128 res = 1;
while (k) {
if (k & 1) res = res * a % mod;
k >>= 1;
a = a * a % mod;
}
return res;
}
int main() {
ll ans = 0;
for (int i = 1; i <= 1000; i ++ ) (ans += qpow(i, i)) %= mod;
cout << ans << "\n";
return 0;
}
49
python
写这个题要方便很多。
# python
from sympy import *
for i in range(1001, 10000, 2):
for j in range(2, (10000 - i) // 2, 2):
if isprime(i) and isprime(i + j) and isprime(i + j * 2):
if set(str(i)) == set(str(i + j)) == set(str(i + j * 2)):
print(i, i + j, i + j * 2)
50
利用双指针扫一遍,复杂度是不足 \(O(n)\) 的,跑起来非常快。
// cpp
#include<bits/stdc++.h>
using namespace std;
const int N = 1e6 + 10;
int primes[N], st[N], cnt;
int main() {
for (int i = 2; i < N; i ++ ) {
if (!st[i]) primes[cnt ++ ] = i;
for (int j = 0; i * primes[j] < N; j ++ ) {
st[i * primes[j]] = 1;
if (i % primes[j] == 0) break;
}
}
int ans = 0, tot = 0;
for (int i = 100; i < cnt; i ++ ) {
int l = 0, r = i;
int res = accumulate(primes, primes + r, 0);
if (res > N) break;
for (; r < cnt; l ++ , r ++ ) {
res += primes[r];
if (res > N) break;
if (!st[res]) {
if (tot < r - l + 1) {
tot = r - l + 1;
ans = res;
}
}
res -= primes[l];
}
}
cout << ans << " " << tot << "\n";
return 0;
}