题意 有 n n n 题的比赛,时长为 t t t,每个题有最早过题时间的约束,每分钟内最多提交一题,任意 k k k 分钟内只能提交 m m m 题,问比赛 A K AK AK 的方案数, 1 ≤ t ≤ 300 , 1 ≤ n ≤ 13 , 1 ≤ m ≤ k ≤ 10 1\le t\le300,1\le n\le13,1\le m\le k\le10 1≤t≤300,1≤n≤13,1≤m≤k≤10
状态表示 f [ i ] [ j ] [ s ] f[i][j][s] f[i][j][s] 表示前 i i i 分钟已经 A C AC AC 了 j j j 题,最后 k k k 分钟过题状态为 s s s 的方案数, s s s 状态中第 i i i 分钟的过题状态位第 k k k 位,最低位为第 i − k + 1 i-k+1 i−k+1 分钟的过题状态
void add(int &x, int y) {
x += y;
if (x >= mod) x -= mod;
}
int main() {
int n, t, k, m; cin >> n >> t >> k >> m;
for (int i = 0; i < n; i ++) {
int x; cin >> x;
num[x] ++;
}
for (int i = 1; i <= t; i ++) sum[i] = sum[i - 1] + num[i];
f[0][0][0] = 1;
for (int i = 1; i <= t; i ++)
for (int s = 0; s < 1 << k; s ++) {
if (__builtin_popcount(s) > m) continue;
for (int j = 0; j <= sum[i]; j ++) {
add(f[i][j][s >> 1], f[i - 1][j][s]);
if (__builtin_popcount(s >> 1) < m)
add(f[i][j + 1][(s >> 1) | (1 << (k - 1))], 1ll * f[i - 1][j][s] * (sum[i] - j) % mod);
}
}
int res = 0;
for (int i = 0; i < 1 << k; i ++) add(res, f[t][n][i]);
cout << res << endl;
return 0;
}
题意 一共 n n n 个人进行 m m m 场比赛,问每场比赛是第一名或者最后一名的概率
double n, m; cin >> n >> m;
printf("%.9lf\n", n == 1 ? 1. : pow(2. / n, m));
题意 序列 { v } i = 1 n \{v\}_{i=1}^n {v}i=1n 具有属性 ( a , b , c ) (a,b,c) (a,b,c) 满足 a , b , c ∈ [ 0 , 255 ] a,b,c\in[0,255] a,b,c∈[0,255],只有当 i i i 比 j j j 的所有属性都较大时,则称 i i i 和 j j j 有严格偏序关系 j ≺ i j\prec i j≺i,它们映射的值满足 j < i jj<i,将 n n n 个数映射到 0 ∼ 255 0\sim255 0∼255 之间的数,且 v 0 v_0 v0 和 v 1 v_1 v1 映射得到的值相等,若不能成立输出 − 1 -1 −1
题解 首先判断 v 0 v_0 v0 和 v 1 v_1 v1 有无严格偏序关系,判断是否能够映射
法一:不断缩小范围,利用与 v [ 0 ] v[0] v[0] 或 v [ 1 ] v[1] v[1] 具有严格偏序关系的 v [ i ] v[i] v[i] 将 [ l , r ] [l,r] [l,r] 从 [ 0 , 255 ] [0,255] [0,255] 缩小,因为需要具备严格偏序关系,则最多只能具有 v 1 ≺ v 2 ≺ . . . ≺ v k v_1\prec v_2\prec ...\prec v_k v1≺v2≺...≺vk 共 k , k ≤ 256 k,k\le256 k,k≤256 个连续严格偏序关系,则映射范围是足够的,无需特判范围不够的情况
struct Color {
int a, b, c;
bool operator< (const Color &x) const {
return a < x.a && b < x.b && c < x.c;
}
};
int max(Color x) { return max(x.a, max(x.b, x.c)); }
int min(Color x) { return min(x.a, min(x.b, x.c)); }
int main() {
int n; cin >> n;
vector<Color> v(n);
vector<int> ans(n);
for (auto &[a, b, c] : v) cin >> a >> b >> c;
if (v[0] < v[1] || v[1] < v[0]) {
cout << -1 << endl;
return 0;
}
int l = 0, r = 255;
for (int i = 2; i < n; i ++) {
if (v[0] < v[i] || v[1] < v[i])
r = min(r, ans[i] = max(v[i]));
else
l = max(l, ans[i] = min(v[i]));
}
ans[0] = ans[1] = (l + r) >> 1;
for (auto i : ans) cout << i << endl;
return 0;
}
法二:拓扑排序
拓扑排序
只适用于 D A G , 有向无环图 ( D i r e c t e d A c y c l i c G r a p h ) DAG,有向无环图(Directed~Acyclic~Graph) DAG,有向无环图(Directed Acyclic Graph)
用队列维护,不断将所有入度为 0 0 0 的点入队,并删除这些点
若删除的点总数不为图中的顶点数,则存在回路,无法进行拓扑排序
合并 v 0 v_0 v0 和 v 1 v_1 v1,对严格偏序关系的点建立边,在这个 D A G DAG DAG 上跑一次拓扑排序进行函数映射即可
struct Color {
int a, b, c;
bool operator< (const Color &x) const {
return a < x.a && b < x.b && c < x.c;
}
};
int main() {
int n; cin >> n;
vector<Color> v(n);
vector<int> ans(n, 256), in(n), g[n];
queue<int> q;
for (auto &[a, b, c] : v) cin >> a >> b >> c;
if (v[0] < v[1] || v[1] < v[0]) {
cout << -1 << endl;
return 0;
}
for (int i = 2; i < n; i ++) {
for (int j = 2; j < n; j ++) {
if (v[j] < v[i]) {
in[j] ++;
g[i].push_back(j);
}
}
if (v[1] < v[i] || v[0] < v[i]) {
in[1] ++;
g[i].push_back(1);
}
if (v[i] < v[0] || v[i] < v[1]) {
in[i] ++;
g[1].push_back(i);
}
}
for (int i = 1; i < n; i ++)
if (!in[i]) {
q.push(i);
ans[i] = 255;
}
while (!q.empty()) {
int t = q.front();
q.pop();
for (auto i : g[t]) {
in[i] --;
if (!in[i]) q.push(i);
ans[i] = min(ans[i], ans[t] - 1);
}
}
ans[0] = ans[1];
for (auto i : ans)
if (i == 256) {
cout << -1 << endl;
return 0;
}
for (auto i : ans) cout << i << endl;
return 0;
}
题意 有式子 a + b = c a~+~b~=~c a + b = c,在其中一个数字的每一位的前后皆可,插入一个数字使得等号成立,若原始也成立也可,输出 Y e s Yes Yes 和修改后的式子,否则输出 N o No No
题解 原始也成立的情况涵盖在将 0 0 0 插入某个数字的最前端,因此只要分三类
bool check(int a, int b) {
for (int i = 0; i <= to_string(a).size(); i ++) {
int base = pow(10, i);
int aa = a % base + a / base * base * 10;
for (int j = 0; j < 10; j ++)
if (aa + base * j == b) return true;
}
return false;
}
void out(int a, int b, int c) {
cout << "Yes" << endl << a << " + " << b << " = " << c << endl;
}
void solve() {
int a, b, c; char ch; cin >> a >> ch >> b >> ch >> c;
if (check(a, c - b)) out(c - b, b, c);
else if (check(b, c - a)) out(a, c - a, c);
else if (check(c, a + b)) out(a, b, a + b);
else cout << "No" << endl;
}