欧拉计划 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 有讲)。

这样的三角形是互质的,所以我们可以把所有倍数都考虑上,如此统计即可。
#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)

浙公网安备 33010602011771号