欧拉计划 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号