欧拉计划 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;
}
posted @ 2025-04-21 16:16  YipChip  阅读(25)  评论(0)    收藏  举报