版权声明:欢迎转载(请附带原链接)ヾ(๑╹◡╹)ノ https://blog.csdn.net/corsica6/article/details/88732034
C.Median Sum
D.Min Max Repetition
最短相同子串长度
字典序最小的串必然前半部分是一段
存在位置 使得前半部分维持到 时,剩余的 满足
从 的后半部分就是一段
二分寻找 即可。
E.Encoding Subsets
区间DP:
设 分别表示01串 子集的方案数和不可分割(长度为1或左右均为括号)的方案数。
边界 ,转移:
转移的时候把强制有循环节按位与即可。
答案是
玄学记搜就过了
code from xyz32768
#include <map>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define For(i, a, b) for (i = a; i <= b; i++)
#define Step(i, a, b, x) for (i = a; i <= b; i += x)
using namespace std;
inline int read() {
int res = 0; bool bo = 0; char c;
while (((c = getchar()) < '0' || c > '9') && c != '-');
if (c == '-') bo = 1; else res = c - 48;
while ((c = getchar()) >= '0' && c <= '9')
res = (res << 3) + (res << 1) + (c - 48);
return bo ? ~res + 1 : res;
}
const int PYZ = 998244353;
map<string, int> f, g;
int F(string); int G(string);
int G(string s) {
if (g[s]) return g[s]; int i, n = s.size(); if (n == 1) return g[s] = s[0] - '0' + 1;
int j, k, res = 0; For (i, 1, n - 1) if (n % i == 0) {
string t = ""; For (j, 1, i) {
int r = 1; Step (k, j - 1, n - 1, i) r &= s[k] - '0';
t += (char) (r + '0');
}
res = (res + F(t)) % PYZ;
}
return g[s] = res;
}
int F(string s) {
if (f[s]) return f[s]; int i, n = s.size(); if (!n) return f[s] = 1;
int res = 0; For (i, 1, n)
res = (res + 1ll * G(s.substr(0, i)) * F(s.substr(i, n)) % PYZ) % PYZ;
return f[s] = res;
}
int main() {
string s; cin >> s; cout << F(s) << endl;
return 0;
}
*F.Arcs on a Circle
Tourist的神题,做是不可能做出来的,题解wxh010910:
取 最大的弧的左端点为原点。其它弧的左端点都可以用一个实数表示。
发现位置整数部分是 的一个随机值,小数部分是 均匀随机的一个实数。我们不关心小数部分的具体值,只关心 条弧的小数部分相对大小。
于是
枚举小数部分相对大小的排列(等概率出现) ,在
个位置上DP:
设
表示已经放上的圆弧状态为
,覆盖最远点为
的方案数。
code from Factorio
#include <bits/stdc++.h>
using namespace std;
double z, f[320][33], t;
int n, c, a[9];
int main() {
cin >> n >> c;
for (int i = 0; i < n; i++) {
cin >> a[i];
}
sort(a, a + n);
do {
memset(f, 0, sizeof f);
f[n * a[n - 1]][0] = 1;
for (int i = 0; i < n * c; i++) {
for (int j = i; j <= n * c; j++) {
for (int k = 0; k < (1 << (n - 1)); k++) {
if (i % n && (k >> (i % n - 1) & 1) == 0) {
f[min(max(j, i + n * a[i % n - 1]), n * c)][k | (1 << (i % n - 1))] += f[j][k];
}
}
}
}
z += f[n * c][(1 << (n - 1)) - 1];
t++;
} while (next_permutation(a, a + n - 1));
printf("%.15f\n", z / t / pow(c, n - 1));
return 0;
}