A. A Prank
Solved.
题意:
给出一串数字,每个数字的范围是$[1, 1000]$,并且这个序列是递增的,求最多擦除掉多少个数字,使得别人一看就知道缺的数字是什么。
思路:
显然,如果缺的这块数字的个数刚好等于右界 - 左界 + 1 那么就可以知道
还需要考虑数据范围,因为是$<= 1000 和 >= 1$ 那么对于两边的边界需要特殊考虑。
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 #define N 110 5 int n, a[N]; 6 7 int main() 8 { 9 while (scanf("%d", &n) != EOF) 10 { 11 for (int i = 1; i <= n; ++i) scanf("%d", a + i); 12 a[0] = 0; a[n + 1] = 1001; 13 int res = 0, tmp = 1; 14 for (int i = 1; i <= n + 1; ++i) 15 { 16 if (a[i] == a[i - 1] + 1) ++tmp; 17 else 18 { 19 res = max(res, tmp - 2); 20 tmp = 1; 21 } 22 } 23 res = max(res, tmp - 2); 24 printf("%d\n", res); 25 } 26 return 0; 27 }
B. Math
Solved.
题意:
给出一个数$n$, 有两种操作。
第一种是乘上一个任意整数$x$
第二种是开方,并且要保证开方后是整数。
求最少经过多少次操作,可以得到一个最小的数$n$
思路:
考虑$n$的质因数分解形式$a_1^{p_1} \cdot a_2^{p_2} \cdot a_3^{p_3} ...$
那么最小的答案就是$a_1 \cdot a_2 \cdot a_3$
因为一个数开方后是整数的话,显然是每个质因子的幂次都是偶数次,开方相当于每个质因子的幂次 $ / 2$
那么显然每个质因子最小的幂次都是1
再考虑最小的次数,因为乘法可以任意乘一个整数,所以如果需要乘法,那么乘法只需要一次。
再考虑开方,如果质因子中的最高幂次不是2的幂次,那么它不断$ / 2$ 肯定需要至少一次乘法操作,使得可以继续开方下去,直到幂次变为1
那么显然要把幂次变成一个第一个大于等于它的2的幂次数,就可以不断$ / 2$
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 #define N 2000010 5 int n, Max, res; 6 int Bit[N], pos[N]; 7 vector <int> v; 8 9 int solve(int x) 10 { 11 if (x == 1) return 0; 12 if (pos[x] == 0) return 1 + lower_bound(Bit + 1, Bit + 1 + 20, x) - Bit; 13 for (auto it : v) if (it != x) return 1 + pos[x]; 14 return pos[x]; 15 } 16 17 int main() 18 { 19 Bit[0] = 1; pos[1] = 0; 20 for (int i = 1; i <= 20; ++i) 21 { 22 Bit[i] = Bit[i - 1] << 1; 23 pos[Bit[i]] = i; 24 } 25 while (scanf("%d", &n) != EOF) 26 { 27 if (n == 1) 28 { 29 puts("1 0"); 30 continue; 31 } 32 v.clear(); 33 res = 1; Max = 0; 34 for (int i = 2; i <= n; ++i) 35 { 36 int tmp = 0; 37 while (n % i == 0) 38 { 39 ++tmp; 40 n /= i; 41 } 42 if (tmp) 43 { 44 res *= i; 45 Max = max(Max, tmp); 46 v.push_back(tmp); 47 } 48 } 49 printf("%d %d\n", res, solve(Max)); 50 } 51 return 0; 52 }
C. Banh-mi
Solved.
题意:
给出一个01串,每次询问区间$[l, r]$ 每次可以将区间内一个数取出,并且答案加上这个数的值,区间内剩余的数也加上这个值,求如何安排取出顺序使得答案最大。
思路:
显然1要在0之前取,
我们考虑区间内有$x个1, y 个 0$
那么考虑取出$x个1的答案$
显然 取出的数是形如 1 2 4 8 .....
是一个等比数列,根据求和公式发现答案为$2^x - 1$
再考虑取出的第一个0的数值为 $2^x - 1$
也是一个等比数列,和为 $(2^x - 1) \cdot (2^y - 1)$
合并两项答案 即$2^x \cdot (2^y - 1)$
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 #define ll long long 5 #define N 100010 6 const ll MOD = (ll)1e9 + 7; 7 int n, q, a[N]; 8 9 ll qmod(ll base, ll n) 10 { 11 ll res = 1; 12 while (n) 13 { 14 if (n & 1) res = res * base % MOD; 15 base = base * base % MOD; 16 n >>= 1; 17 } 18 return res; 19 } 20 21 int main() 22 { 23 while (scanf("%d%d", &n, &q) != EOF) 24 { 25 a[0] = 0; 26 for (int i = 1; i <= n; ++i) scanf("%1d", a + i), a[i] += a[i - 1]; 27 for (int i = 1, l, r; i <= q; ++i) 28 { 29 scanf("%d%d", &l, &r); 30 int x = a[r] - a[l - 1], y = (r - l + 1) - x; 31 if (x == 0) 32 { 33 puts("0"); 34 continue; 35 } 36 printf("%lld\n", qmod(2, y) * (qmod(2, x) - 1 + MOD) % MOD); 37 } 38 } 39 return 0; 40 }
D. Fun with Integers
Solved.
题意:给出一个数$n$,任意$|a| , |b| < n$ 并且满足 $|a| |b| 互为倍数关系$ 那么答案加上这个倍数,并且这一对$|a|, |b|$不再提供贡献,并且倍数关系$|x| > 1$
思路:
考虑一个数$x$, 那么在$[1, n]$ 中是它的倍数的数一共有 $y = \lfloor \frac {n}{x} \rfloor \cdot 2$ 个 因为还有负的
那么这个数的贡献是$\sum_2 ^y \cdot 2$ 再考虑 $-x$ 也会提供一样的贡献 即答案要乘2
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 #define ll long long 5 int n; 6 7 int main() 8 { 9 while (scanf("%d", &n) != EOF) 10 { 11 ll res = 0; 12 for (int i = 2; i <= n; ++i) 13 { 14 ll x = n / i; 15 res += 2ll * (x + 2) * (x - 1); 16 } 17 printf("%lld\n", res); 18 } 19 return 0; 20 }
E. Company
Unsolved.
题意:
在一棵树中,每次选择一个区间$[l, r]$ 最多删除一个点,使得这个区间内所有点的$lca$ 的深度最大。
F. Upgrading Cities
Unsolved.