A:msc和mas
Solved.
考虑斐波那契数列,即最多加45次即会超过1e9,直接暴力即可
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 int a, b, l; 5 6 int solve(int st) 7 { 8 int A = a, B = b; 9 while (1) 10 { 11 if (st == 1) 12 { 13 if (A > l) return printf("Yes"); 14 else 15 { 16 int B0 = B; 17 while (B < 2 * B0) B += A; 18 } 19 } 20 else 21 { 22 if (B > l) return printf("No"); 23 else 24 { 25 int A0 = A; 26 while (A < 2 * A0) A += B; 27 } 28 } 29 st ^= 1; 30 } 31 } 32 33 int main() 34 { 35 while (scanf("%d%d%d", &a, &b, &l) != EOF) 36 { 37 solve(1); putchar(' '); 38 solve(0); putchar('\n'); 39 } 40 return 0; 41 }
B:msc和mcc
Solved.
考虑如果有一个区间满足,那么左右两边扩展区间肯定也是满足的
再考虑从左到右,如果$1-x满足,那么2-y满足的话, 显然有y >= x$
那么只需要双指针找到以i为左界,找到最近的右界,那么这个点的贡献就是n - r + 1
再考虑怎么判断是否合法
不难发现,只有mscmcc 和 mccmsc 两种情况,注意其中可以加入其他字符,但是最终取出的子序列都会归结到这两种情况 都判断一下即可
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 #define ll long long 5 #define N 100010 6 int n; 7 char str[N]; 8 set <int> m, s, c; 9 int st_m[2], pos_s, pos_c[2]; 10 11 bool check1() 12 { 13 // mscmcc 14 if (s.upper_bound(st_m[0]) == s.end()) return false; 15 pos_s = *s.upper_bound(st_m[0]); 16 if (c.upper_bound(pos_s) == c.end()) return false; 17 pos_c[0] = *c.upper_bound(pos_s); 18 if (c.upper_bound(max(st_m[1], pos_c[0])) == c.end()) return false; 19 pos_c[1] = *c.upper_bound(max(st_m[1], pos_c[0])); 20 if (c.upper_bound(pos_c[1]) == c.end()) return false; 21 return true; 22 } 23 24 bool check2() 25 { 26 // mccmsc 27 if (c.upper_bound(st_m[0]) == c.end()) return false; 28 pos_c[0] = *c.upper_bound(st_m[0]); 29 if (c.upper_bound(pos_c[0]) == c.end()) return false; 30 pos_c[1] = *c.upper_bound(pos_c[0]); 31 if (s.upper_bound(st_m[1]) == s.end()) return false; 32 pos_s = *s.upper_bound(st_m[1]); 33 if (c.upper_bound(max(pos_s, pos_c[1])) == c.end()) return false; 34 return true; 35 } 36 37 bool ok() 38 { 39 if (m.size() < 2) return false; 40 if (s.size() < 1) return false; 41 if (c.size() < 3) return false; 42 st_m[0] = *m.begin(); m.erase(m.begin()); 43 st_m[1] = *m.begin(); m.insert(st_m[0]); 44 if (check1()) return true; 45 if (check2()) return true; 46 return false; 47 } 48 49 int main() 50 { 51 while (scanf("%d", &n) != EOF) 52 { 53 m.clear(); s.clear(); c.clear(); 54 ll res = 0; 55 scanf("%s", str + 1); 56 for (int i = 1, r = 0; i <= n; ++i) 57 { 58 while (r < n && !ok()) 59 { 60 ++r; 61 if (str[r] == 'm') m.insert(r); 62 else if (str[r] == 's') s.insert(r); 63 else c.insert(r); 64 } 65 if (!ok()) break; 66 res += n - r + 1; 67 if (str[i] == 'm') m.erase(i); 68 else if (str[i] == 's') s.erase(i); 69 else c.erase(i); 70 } 71 printf("%lld\n", res); 72 } 73 return 0; 74 }
C:msc的宠物
Upsolved.
先二分答案,再DP求解最少需要删去的边数。
设$g[u] 表示 以 u 为根的子树下最少需要删去的边数,f[u][x] 表示以u为根的子树下u所处的连通块中点权最大值为x的情况下最少需要删去的边数$
$对于u 和 v 如果 a[u] < x 并且 a[v] < x 并且 abs(a[u] - a[v]) < x 那么 u 和 v 就可以同属一个连通块 $
$那么转移就是 f[u][x] += min(g[v] +1, f[v][x])$
其他情况的转移都是 $f[u][x] += g[v] +1$
最后 $g[u] = min(f[u][x])$
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 #define N 1010 5 #define INF 0x3f3f3f3f 6 #define ll long long 7 int n, k, a[N], f[N][N], g[N]; ll x; 8 vector <int> G[N]; 9 10 void dp(int u, int fa = 0) 11 { 12 for (auto v : G[u]) if (v != fa) 13 { 14 dp(v, u); 15 for (int i = 1; i <= n; ++i) 16 { 17 if (a[u] <= a[i] && a[v] <= a[i] && abs(a[u] - a[v]) <= x) 18 f[u][i] += min(g[v] + 1, f[v][i]); 19 else 20 f[u][i] += g[v] + 1; 21 } 22 } 23 for (int i = 1; i <= n; ++i) 24 g[u] = min(g[u], f[u][i]); 25 } 26 27 bool check() 28 { 29 memset(g, 0x3f, sizeof g); 30 for (int i = 1; i <= n; ++i) for (int j = 1; j <= n; ++j) 31 f[i][j] = (abs(a[i] - a[j]) <= x) ? 0 : INF; 32 dp(1); 33 return g[1] <= k; 34 } 35 36 void Run() 37 { 38 while (scanf("%d%d", &n, &k) != EOF) 39 { 40 for (int i = 1; i <= n; ++i) scanf("%d", a + i); 41 for (int i = 1, u, v; i < n; ++i) 42 { 43 scanf("%d%d", &u, &v); 44 G[u].push_back(v); 45 G[v].push_back(u); 46 } 47 ll l = 0, r = 2000000000, res = -1; 48 while (r - l >= 0) 49 { 50 x = (l + r) >> 1; 51 if (check()) 52 { 53 res = x; 54 r = x - 1; 55 } 56 else 57 l = x + 1; 58 } 59 printf("%d\n", res); 60 } 61 } 62 63 int main() 64 { 65 #ifdef LOCAL 66 freopen("Test.in", "r", stdin); 67 #endif 68 69 Run(); 70 return 0; 71 }
D:msc的背包
Unsolved.
E:msc的序列
Unsolved.
F:msc的无向图
Unsolved.