标签:define 离线 ems continue mem 构造 操作 其他 less
A. Parity
签.
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 #define N 100010 5 int b, k, a[N]; 6 7 int main() 8 { 9 while (scanf("%d%d", &b, &k) != EOF) 10 { 11 int res = 0; 12 for (int i = 1; i <= k; ++i) scanf("%d", a + i); 13 int base = 1; 14 for (int i = k; i >= 1; --i) 15 { 16 res = (res + a[i] * base % 2) % 2; 17 base = base * b % 2; 18 } 19 puts(res % 2 ? "odd" : "even"); 20 } 21 return 0; 22 }
做的时候卡了一会儿
因为想用费马小定理
认为
$b^x = b^{(x \% \phi(m))} \pmod m$
然后幂次都变为$0$
就直接加起来$模2判断一下就好了$
$但是没有考虑到0^0次的问题$
$在这里如果b % 2 == 0, 那么带b的项都为0$
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 #define N 100010 5 int b, k, a[N]; 6 7 int main() 8 { 9 while (scanf("%d%d", &b, &k) != EOF) 10 { 11 int res = 0; 12 for (int i = 1; i <= k; ++i) scanf("%d", a + i); 13 for (int i = 1; i <= k; ++i) 14 res = (res + a[i] % 2) % 2; 15 if (b % 2 == 0) res = a[k]; 16 puts(res % 2 ? "odd" : "even"); 17 } 18 return 0; 19 }
B. Tape
签.
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 #define N 100010 5 int n, m, k; 6 int b[N]; 7 8 int main() 9 { 10 while (scanf("%d%d%d", &n, &m, &k) != EOF) 11 { 12 --k; 13 for (int i = 1; i <= n; ++i) scanf("%d", b + i); 14 int res = b[n] - b[1] + 1; 15 priority_queue <int> pq; 16 for (int i = 2; i <= n; ++i) pq.push(b[i] - b[i - 1] - 1); 17 while (!pq.empty() && k--) 18 { 19 res -= pq.top(); 20 pq.pop(); 21 } 22 printf("%d\n", res); 23 } 24 return 0; 25 }
C. Meaningless Operations
Solved.
题意:
给出一个数$a$
$定义(f(a) = max_{1 <= b < a} gcd(a \oplus b, a \& b))$
给出$f(a)$
思路:
考虑$gcd(x, 0) = x$
那么我们构造$(a \& b) = 0, 并且 (a \oplus b)最大即可$
$对于2^x - 1 这种东西是没法构造的$
$考虑这样的数不多,提前打表即可$
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 int q, x; 5 map <int, int> ans; 6 7 int solve(int x) 8 { 9 if (ans.find(x) != ans.end()) return ans[x]; 10 int res; 11 for (int i = 24; i >= 0; --i) if (((x >> i) & 1)) 12 { 13 res = (1 << (i + 1)) - 1; 14 break; 15 } 16 return ans[x] = res; 17 } 18 19 int main() 20 { 21 ans[1] = 1, 22 ans[3] = 1, 23 ans[7] = 1, 24 ans[15] = 5, 25 ans[31] = 1, 26 ans[63] = 21, 27 ans[127] = 1, 28 ans[255] = 85, 29 ans[511] = 73, 30 ans[1023] = 341, 31 ans[2047] = 89, 32 ans[4095] = 1365, 33 ans[8191] = 1, 34 ans[16383] = 5461, 35 ans[32767] = 4681, 36 ans[65535] = 21845, 37 ans[131071] = 1, 38 ans[262143] = 87381, 39 ans[524287] = 1, 40 ans[1048575] = 349525, 41 ans[2097151] = 299593, 42 ans[4194303] = 1398101, 43 ans[8388607] = 178481, 44 ans[16777215] = 5592405, 45 ans[33554431] = 1082401; 46 while (scanf("%d", &q) != EOF) 47 { 48 while (q--) 49 { 50 scanf("%d", &x); 51 printf("%d\n", solve(x)); 52 } 53 } 54 return 0; 55 }
D. Jongmah
Upsolved.
题意:
有一些数字,三个相同的数字消去
三个连续的也可以消去
求最多消去多少组
思路:
$dp[i][j][k] 表示到第i大的数, 第i - 2大的数还余了j个, 第i - 1个数还余了k个$
$的最大消去的组数$
$转移的时候注意能跟前面的余数组成连续的就组成连续的$
$因为和前面余数组成连续的只需要出一张牌就获得1的贡献$
$如果消去当前三张相同的需要三张牌,至少是不会亏的$
$注意转移的时候要把前面的余数也剪掉$
$再考虑每张牌最多出5张和前面和后面的其他牌组成连续的$
$那么j, k的状态只有6个$
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 #define ll long long 5 #define N 1000010 6 int n, m, a[N]; 7 ll f[2][6][6]; 8 9 int main() 10 { 11 while (scanf("%d%d", &n, &m) != EOF) 12 { 13 memset(a, 0, sizeof a); 14 memset(f, -1, sizeof f); 15 for (int i = 1, x; i <= n; ++i) 16 { 17 scanf("%d", &x); 18 ++a[x]; 19 } 20 if (m <= 2) 21 { 22 printf("%d\n", a[1] / 3 + a[2] / 3); 23 continue; 24 } 25 ll res = 0; 26 for (int i = 0; i < 6; ++i) 27 for (int j = 0; j < 6; ++j) 28 if (a[1] >= i && a[2] >= j) 29 f[2 & 1][i][j] = (a[1] - i) / 3 + (a[2] - j) / 3; 30 //for (int i = 1; i <= m; ++i) printf("%d%c", a[i], " \n"[i == m]); 31 for (int i = 3; i <= m; ++i) 32 { 33 for (int j = 0; j < 6; ++j) 34 for (int k = 0; k < 6; ++k) 35 f[i & 1][j][k] = -1; 36 for (int j = 0; j < 6; ++j) 37 { 38 for (int k = 0; k < 6; ++k) if (f[(i & 1) ^ 1][j][k] != -1) 39 { 40 for (int o = 0; o < 6; ++o) 41 { 42 int need = min(j, min(a[i] - o, k)); 43 ll base = f[(i & 1) ^ 1][j][k]; 44 if (a[i] >= o) 45 { 46 for (int w = 0; w <= need; ++w) 47 f[i & 1][k - w][o] = max(f[i & 1][k - w][o], base + (a[i] - o - w) / 3 + w); 48 } 49 } 50 } 51 } 52 //for (int j = 0; j < 3; ++j) 53 // for (int k = 0; k < 3; ++k) 54 // printf("%d %d %d %lld\n", i, j, k, f[i][j][k]); 55 } 56 for (int i = 0; i < 6; ++i) 57 for (int j = 0; j < 6; ++j) 58 res = max(res, f[m & 1][i][j]); 59 printf("%lld\n", res); 60 } 61 return 0; 62 }
E. Magic Stones
Upsolved.
题意:
有一个数字序列$A[], 每次可以选择一个i \in [2, n - 1]$
$使得 A[i] = A[i + 1] + A[i - 1] - A[i]$
问能否经过一些这样的操作,使得$A[] -> B[]$
思路:
我们令$d[i] = A[i + 1] - A[i]$
我们考虑$上述的那个操作$
$d_i = A[i + 1] - (A[i + 1] + A[i - 1] - A[i]) = A[i] - A[i - 1] = d_{i - 1}$
同理
$d_{i - 1} = d_{i}$
我们注意到,这个操作变成了交换元素
$那么把B[]数组也变成差分数组,如果两个差分数组通过任意交换后相同$
$那么原序列通过以系列操作也可以相同$
$即排个序判断是否相同即可,再注意一下第一个是否相同$
F. Nearest Leaf
Upsolved.
题意:
给出一个树, 询问$离v节点最近叶子节点的距离$
注意给出的点序是$DFS序$
思路:
将询问离线,令根为$1$
$考虑如果询问1号点,那么跑一遍DFS,将所有点的距离丢进线段树$
$查最小值即可$
那么对于一个点$x$
我们考虑从线段树里面维护的距离是到它父亲$y的距离$
$那么我们要把这个距离转变成到x的距离$
$可以发现,它子树内的点都需要减去一条边,就是它父亲到它那条边$
$它子树外的点都需要加上一条边,是它父亲到它那条边$
$子树内的点是连续的,所以可以在线段树上操作$
标签:define 离线 ems continue mem 构造 操作 其他 less
原文地址:https://www.cnblogs.com/Dup4/p/10355916.html