欧拉计划 51~60
51
来分析分析有什么样的交换才满足,容易发现,替换位数不是 \(3\) 的倍数时,在 \(0 \sim 9\) 的替换中,至少会让数位和取 \(3\) 次 \(3\) 的倍数,因此最多只有 \(7\) 个质数,因此替换位数一定是 \(3\) 的倍数位,我们想要尽可能小,不妨先假设只有 \(3\) 位替换,再由于 \(5\) 位数已经有 \(56003\) 这个极小量了,我们考虑试试能不能用 \(6\) 位数构造一个解,事实证明,我们的猜测是正确的。
由于实现过程比较简陋,所以对 \(d\) 进行全排会重复输出 \(3!\) 次,但是答案能够求出,并且效率较高。
# python
from sympy import *
from itertools import *
number = ''
for i in range(10): number += str(i) * 3
for i in list(set(combinations(number, 3))):
for check in permutations(''.join(map(str, i)) + 'd' * 3):
check = ''.join(map(str, check))
if check[0] == '0': continue
cnt = 0
minn = 1e7
for d in range(10):
res = check.replace('d', str(d))
if res[0] != '0' and isprime(int(res)):
cnt += 1
minn = min(minn, int(res))
if cnt == 8:
print(minn)
52
根据一些数学常识,\(142857\) 是一个可疑最小值,在比它小的地方搜一次即可。
# python
from sympy import *
from itertools import *
for i in range(1, 142858):
lis = set([''.join(map(str, set(str(i * x)))) for x in range(1, 7)])
if len(lis) == 1:
print(i)
53
# python
from sympy import *
from itertools import *
ans = 0
for i in range(101):
for j in range(101):
if binomial(i, j) > 1e6:
ans += 1
print(ans)
54
我的天哪 python 大人!
# python
from sympy import *
from itertools import *
cmp = [str(i) for i in range(1, 10)] + ['T'] + ['J'] + ['Q'] + ['K'] + ['A']
reflection = {}
for i in range(len(cmp)):
reflection[cmp[i]] = i
def high(numbers):
result = 0
for i in range(len(numbers)):
result += pow(14, i) * numbers[i]
return result
def check_level(player):
same = len(set([player[i][1] for i in range(5)])) == 1
numbers = sorted([reflection[player[i][0]] for i in range(5)])
isflush = len(set(numbers)) == 5 and numbers[4] - numbers[0] == 4
if same and isflush: return [8, high(numbers)]
if isflush: return [4, high(numbers)]
if same: return [5, high(numbers)]
cnt = [0 for _ in range(14)]
for i in numbers:
cnt[i] += 1
if cnt.count(4): return [7, cnt.index(4)]
if cnt.count(3):
if cnt.count(1): return [3, cnt.index(3)]
return [6, cnt.index(3)]
if cnt.count(2) == 2: return [2, high([cnt.index(1)] + [x for (x, y) in enumerate(cnt) if y == 2])]
if cnt.count(2) == 1: return [1, high([x for (x, y) in enumerate(cnt) if y == 1] + [cnt.index(2)])]
return [0, high(numbers)]
ans = 0
with open('poker.txt', 'r') as f:
for lines in f.readlines():
lines = lines.split()
player1 = [lines[i] for i in range(5)]
player2 = [lines[i + 5] for i in range(5)]
level1 = check_level(player1)
level2 = check_level(player2)
if level1[0] > level2[0]: ans += 1
elif level1[0] == level2[0] and level1[1] > level2[1]: ans += 1
print(ans)
特别的,HackerRank 上的测试用例有地龙(A2345顺子),修改一下代码也可以通过。
#python
from itertools import *
cmp = [str(i) for i in range(1, 10)] + ['T'] + ['J'] + ['Q'] + ['K'] + ['A']
reflection = {}
for i in range(len(cmp)):
reflection[cmp[i]] = i
def high(numbers):
result = 0
for i in range(len(numbers)):
result += pow(14, i) * numbers[i]
return result
def check_level(player):
same = len(set([player[i][1] for i in range(5)])) == 1
numbers = sorted([reflection[player[i][0]] for i in range(5)])
isflush = len(set(numbers)) == 5 and numbers[4] - numbers[0] == 4
isminflush = len(set(numbers)) == 5 and numbers[3] == 4 and numbers[4] == 13
if isminflush: isflush = 1
if same and isflush: return [8, numbers[1]]
if isflush: return [4, numbers[1]]
if same: return [5, high(numbers)]
cnt = [0 for _ in range(14)]
for i in numbers:
cnt[i] += 1
if cnt.count(4): return [7, cnt.index(4)]
if cnt.count(3):
if cnt.count(1): return [3, cnt.index(3)]
return [6, cnt.index(3)]
if cnt.count(2) == 2: return [2, high([cnt.index(1)] + [x for (x, y) in enumerate(cnt) if y == 2])]
if cnt.count(2) == 1: return [1, high([x for (x, y) in enumerate(cnt) if y == 1] + [cnt.index(2)])]
return [0, high(numbers)]
n = int(input())
while n > 0:
n -= 1
lines = input()
lines = lines.split()
player1 = [lines[i] for i in range(5)]
player2 = [lines[i + 5] for i in range(5)]
level1 = check_level(player1)
level2 = check_level(player2)
if level1[0] > level2[0]: print('Player 1')
elif level1[0] == level2[0] and level1[1] > level2[1]: print('Player 1')
else: print('Player 2')
55
没什么难度,cpp 需要开 int128 罢了。
# python
from sympy import *
from itertools import *
cnt = 0
for i in range(1, 10000):
x = i
for j in range(50):
x += int(str(x)[::-1])
if str(x) == str(x)[::-1]:
cnt += 1
print(i, x)
break
print(9999 - cnt)
56
用 cpp 写需要使用高精度。
# python
from sympy import *
from itertools import *
ans = 0
for i in range(100):
for j in range(100):
x = pow(i, j)
ans = max(ans, sum(list(map(int, list(str(x))))))
print(ans)
57
利用 Fraction 分数类进行计算即可。
# python
from sympy import *
from itertools import *
from fractions import *
inv2 = Fraction(1, 2)
lis = [inv2]
for i in range(1000):
lis.append(Fraction(1, 2 + lis[-1]))
ans = 0
for f in lis:
f += 1
if len(str(f.numerator)) > len(str(f.denominator)):
ans += 1
print(ans)
58
算出四个方向的数列,发现右下方向是完全平方数,然后枚举剩余三个方向就可以解决了。
# python
from sympy import *
from itertools import *
from fractions import *
def f1(x): return 4 * x ** 2 - 10 * x + 7
def f2(x): return 4 * x ** 2 - 8 * x + 5
def f3(x): return 4 * x ** 2 - 6 * x + 3
total = 1
cnt = 0
i = 1
while(1):
i += 1
total += 4
cnt += isprime(f1(i))
cnt += isprime(f2(i))
cnt += isprime(f3(i))
if cnt / total < 0.1: break
print(i * 2 - 1)
59
暴力枚举密钥,检测一些常用单词(冠词,连词,介词),这里检测的是 the,合适的控制范围即可。
# python
from sympy import *
from itertools import *
from pwn import *
with open('cipher.txt', 'r') as f:
ciphertext = f.readline().split(',')
ciphertext = b''.join(chr(int(i)).encode('utf-8') for i in ciphertext)
for key in product(string.ascii_lowercase, repeat=3):
plaintext = xor(key, ciphertext)
if plaintext.count(b'the') > 8:
print(plaintext)
ans = 0
for s in plaintext:
ans += s
print(ans)
60
剪枝神题,素数肯定不能全存下来,我们使用 Miller Rabin 算法判素,将每个数字都够匹配的对存入哈希表中,预处理,防止搜索时重复搜索,在 HackerRank 上可以跑入两秒内。
// cpp
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 20010;
int primes[N], st[N], len[N], cnt;
vector<int> possible_prime[N];
unordered_map<int, int> exist[N];
int n, k;
vector<int> vec, ans;
ll qpow(ll a, ll k, ll mod) {
ll res = 1;
while (k) {
if (k & 1) res = res * a % mod;
k >>= 1;
a = a * a % mod;
}
return res;
}
vector<int> base = {2, 7, 61};
bool check(ll a, ll p) {
ll d = p - 1, r = 0;
while (!(d & 1)) r ++ , d >>= 1;
ll now = qpow(a, d, p);
if (now == 1) return 1;
while (r -- ) {
if (now == p - 1) return 1;
now = now * now % p;
}
return 0;
}
bool Miller_Rabin(int x) {
if (x < n) return !st[x];
for (auto a : base) if (!check(a, x)) return 0;
return 1;
}
void init(int n) {
st[1] = len[0] = 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 = 1; i < n; i ++ ) len[i] = len[i / 10] * 10;
for (int i = 1; i < cnt; i ++ ) {
for (int j = i + 1; j < cnt; j ++ ) {
if (!Miller_Rabin(primes[i] * len[primes[j]] + primes[j])) continue;
if (!Miller_Rabin(primes[j] * len[primes[i]] + primes[i])) continue;
possible_prime[i].push_back(j);
exist[i][j] = 1;
}
}
}
void dfs(int now, int d) {
if (d == k) {
int res = 0;
for (int i : vec) res += primes[i];
return ans.push_back(res), void();
}
for (int nxt : possible_prime[now]) {
int flag = 0;
for (int num : vec) {
if (!exist[num].count(nxt)) {
flag = 1;
break;
}
}
if (flag) continue;
vec.push_back(nxt);
dfs(nxt, d + 1);
vec.pop_back();
}
}
void solve() {
init(n);
// for (int i = 1; i < cnt; i ++ ) {
// cout << "prime = " << primes[i] << "\n";
// if (possible_prime[i].size()) cout << "next primes: ";
// for (int num : possible_prime[i]) {
// cout << primes[num] << " \n"[num == possible_prime[i].back()];
// }
// }
for (int i = 1; i < cnt; i ++ ) vec = {i}, dfs(i, 1);
sort(ans.begin(), ans.end());
for (auto i : ans) cout << i << "\n";
}
int main() {
cin >> n >> k;
// clock_t start, end;
// start = clock();
solve();
// end = clock();
// cout << "time = " << (double)(end - start) * 1000 / CLOCKS_PER_SEC << "ms" << "\n";
return 0;
}

浙公网安备 33010602011771号