欧拉计划 31~40

31

完全背包求方案数,具体参见代码。

// cpp
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1e5 + 10;

int main() {
    vector<ll> f(201);
    int d[] = {1, 2, 5, 10, 20, 50, 100, 200};
    f[0] = 1;
    for (int i = 0; i < 8; i ++ ) {
        for (int j = d[i]; j <= 200; j ++ ) {
            if (j >= d[i]) {
                f[j] += f[j - d[i]];
            }
        }
    }
    cout << f[200];
    return 0;
}

32

容易发现,合法的乘积只能是四位数,模拟即可。

// cpp
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1e5 + 10;

int calc(vector<int> num, int p) {
    int a = 0, b = 0, c = 0;
    if (p == 0) {
        a = num[0];
        b = num[1] * 1000 + num[2] * 100 + num[3] * 10 + num[4];
        c = num[5] * 1000 + num[6] * 100 + num[7] * 10 + num[8];
    }
    else if (p == 1) {
        a = num[0] * 10 + num[1];
        b = num[2] * 100 + num[3] * 10 + num[4];
        c = num[5] * 1000 + num[6] * 100 + num[7] * 10 + num[8];
    }
    if (a * b == c) return c;
    return 0;
}

int main() {
    vector<int> a(9), ans;
    iota(a.begin(), a.end(), 1);
    do {
        for (int i = 0; i <= 1; i ++ ) {
            if (calc(a, i)) {
                ans.push_back(calc(a, i));
                cout << calc(a, i) << "\n";
            }
        }
    } while (next_permutation(a.begin(), a.end()));
    sort(ans.begin(), ans.end());
    ans.erase(unique(ans.begin(), ans.end()), ans.end());
    cout << accumulate(ans.begin(), ans.end(), 0);
    return 0;
}

33

简单模拟,合法的分数有 \(16/64, \, 19/95, \, 26/65, \, 49/98\).

// cpp
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1e5 + 10;

bool check(int a, int b) {
    int x1 = a % 10, x2 = a / 10;
    int y1 = b % 10, y2 = b / 10;
    if (!y1 || !y2 || !x1 || !x2) return 0;
    if (a * y1 == b * x1 && x2 == y2) return 1;
    if (a * y2 == b * x1 && x2 == y1) return 1;
    if (a * y1 == b * x2 && x1 == y2) return 1;
    if (a * y2 == b * x2 && x1 == y1) return 1;
    return 0;
}

int main() {
    ll a = 1, b = 1;
    for (int i = 10; i <= 99; i ++ ) {
        for (int j = i + 1; j <= 99; j ++ ) {
            if (check(i, j)) {
                a *= i;
                b *= j;
                cout << i << " " << j << "\n";
            }
        }
    }
    cout << b / __gcd(a, b);
    return 0;
}

34

考虑 \(9! = 362880\)\(8 \times 9! = 2903040\),故合法的数不超过 \(7 \times 9!\),对每个数进行检查即可。

# python
from sympy import *

def calc(t):
    x = t
    res = 0
    while x > 0:
        res += factorial(x % 10)
        x //= 10
    return res == t

ans = 0
for i in range(10, 7 * factorial(9) + 1):
    if (calc(i)):
        ans += i
print(ans)

35

按要求模拟即可,注意特判前导零的存在,如果存在前导零是不合法的。

// cpp
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1e6 + 10;
int primes[N], st[N], cnt;

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

bool check(int x, int ori) {
    if (st[x]) return 0;
    int len = 1; while(len * 10 <= x) len *= 10;
    if (x % len < len / 10) return 0;
    x = x % len * 10 + x / len;
    if (x == ori) return 1;
    return check(x, ori);
}

int main() {
    init(), st[1] = 1;
    int ans = 0;
    for (int i = 2; i < N; i ++ ) {
        if (check(i, i)) ans ++ , cout << i << "\n";
    }
    cout << ans;
    return 0;
}

36

字符串翻转用 python 比较好些

# python
from sympy import *

ans = 0
for i in range(1, 1000000, 2):
    if str(i)[::-1] == str(i) and str(bin(i))[2:][::-1] == str(bin(i))[2:]:
        ans += i
print(ans)

37

写一个检查函数即可

// cpp
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1e6 + 10;
int primes[N], st[N], cnt;

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

bool check1(int x) {
    if (!x) return 1;
    if (st[x]) return 0;
    return check1(x / 10); 
}

bool check2(int x) {
    if (!x) return 1;
    if (st[x]) return 0;
    int len = 1; while (len * 10 <= x) len *= 10;
    return check2(x % len);
}

int main() {
    init(), st[1] = 1;
    int ans = 0;
    for (int i = 10; i < N; i ++ ) {
        if (check1(i) && check2(i)) ans += i, cout << i << "\n";
    }
    cout << ans;
    return 0;
}

38

首先进行分析:

  • \(n = 2\) 时,显然需要 \(4\) 位数字才可以拼出 \(1 \sim 9\),想让这个数更大,显然要尽量把 \(x\) 取得最大,再把 \(2x\) 拼上去。
  • \(n = 3\) 时,仅 \(3\) 位数字可行,且第一部分小于等于 \(321\),如果产生进位则不合法了。
  • \(n = 4\) 时,仅 \(2\) 位数字可行,\(x, \, 2x, \, 3x\) 均为 \(2\) 位数,\(4x\)\(3\) 位数,第一部分小于等于 \(32\),其余不合法。
  • \(n = 5\) 时,第一个数是 \(6 \sim 9\) 可行,其余数字不合法。
  • \(\cdots\)

事实上,我们取 \(n = 2\) 倒序遍历就可以得到一个极大值了。

# python
from sympy import *

ans = 0
for i in range(9999, 9000, -1):
    res = str(i) + str(i << 1)
    if set(res) == set("123456789"):
        ans = max(ans, int(res))
print(ans)

39

利用 本原毕达哥拉斯三元组生成树 获得所有本原三角形(这部分在 #94 有讲)。

image

这样的三角形是互质的,所以我们可以把所有倍数都考虑上,如此统计即可。

#python
from sympy import *

A = Matrix([[1, -2, 2],
            [2, -1, 2],
            [2, -2, 3]])
B = Matrix([[1, 2, 2],
            [2, 1, 2],
            [2, 2, 3]])
C = Matrix([[-1, 2, 2],
            [-2, 1, 2],
            [-2, 2, 3]])
O = Matrix([[3], [4], [5]])
triangles = [O]
cnt = [0 for _ in range(1001)]
for ori in triangles:
    for i in range(1, 1000):
        if sum(ori) * i > 1000: break
        cnt[sum(ori) * i] += 1
    if sum(A * ori) <= 1000: triangles.append(A * ori)
    if sum(B * ori) <= 1000: triangles.append(B * ori)
    if sum(C * ori) <= 1000: triangles.append(C * ori)
print(cnt.index(max(cnt)))

40

按照题意模拟即可,为了避免空间复杂度爆炸,动态的插入数字即可。

# python
from sympy import *

Str = ""
ans = 1
d = 1
num = 1
while d <= 1000000:
    if len(Str) < d:
        Str += str(num)
        num += 1
    if d == 1 or d == 10 or d == 100 or d == 1000 or d == 10000 or d == 100000:
        ans *= int(Str[d - 1])
    d += 1

print(ans)
posted @ 2025-03-24 21:06  YipChip  阅读(14)  评论(0)    收藏  举报