「PKUWC2018/PKUSC2018」试题选做

最近还没想好报THUSC还是PKUSC,THU发我的三类约(再来一瓶)不知道要不要用,甚至不知道营还办不办,协议还有没有用。所以这些事情就暂时先不管了,PKU的题还是不错的,就刷一刷划水。因为比较简单,所以就不单独写博客了。

loj2537 Minimax

数据结构题,两个 \(\log\) 直接启发式合并,一个 \(\log\) 需要转移的时候多维护一些东西。

对于每个节点维护一下选择其子树里每个叶子的权值的概率,线段树合并转移即可。

code

  1. /*program by mangoyang*/
  2. #include <bits/stdc++.h>
  3. #define inf (0x7f7f7f7f)
  4. #define Max(a, b) ((a) > (b) ? (a) : (b))
  5. #define Min(a, b) ((a) < (b) ? (a) : (b))
  6. typedef long long ll;
  7. using namespace std;
  8. template <class T>
  9. inline void read(T &x){
  10. int ch = 0, f = 0; x = 0;
  11. for(; !isdigit(ch); ch = getchar()) if(ch == '-') f = 1;
  12. for(; isdigit(ch); ch = getchar()) x = x * 10 + ch - 48;
  13. if(f) x = -x;
  14. }
  15. const int M = 1e9, N = 300005, mod = 998244353;
  16. int a[N], rt[N], P, n, ans;
  17. vector<int> g[N];
  18. vector<pair<int, int> > Ans;
  19. namespace Seg{
  20. #define mid ((l + r) >> 1)
  21. int s[N*30], tag[N*30], lc[N*30], rc[N*30], size;
  22. inline void init(){ for(int i = 1; i < N * 30; i++) tag[i] = 1; }
  23. inline void pushdown(int u){
  24. if(tag[u] == 1) return;
  25. if(lc[u]){
  26. s[lc[u]] = 1ll * tag[u] * s[lc[u]] % mod;
  27. tag[lc[u]] = 1ll * tag[lc[u]] * tag[u] % mod;
  28. }
  29. if(rc[u]){
  30. s[rc[u]] = 1ll * tag[u] * s[rc[u]] % mod;
  31. tag[rc[u]] = 1ll * tag[rc[u]] * tag[u] % mod;
  32. }
  33. tag[u] = 1;
  34. }
  35. inline void insert(int &u, int l, int r, int pos){
  36. if(!u) u = ++size;
  37. if(l == r) return (void) (s[u] = 1);
  38. if(pos <= mid) insert(lc[u], l, mid, pos);
  39. else insert(rc[u], mid + 1, r, pos);
  40. s[u] = s[lc[u]] + s[rc[u]];
  41. }
  42. inline int merge(int x, int y, int sumx, int sumy){
  43. if(!x){
  44. if(!sumx) return y;
  45. s[y] = 1ll * s[y] * sumx % mod;
  46. tag[y] = 1ll * tag[y] * sumx % mod;
  47. return y;
  48. }
  49. if(!y){
  50. if(!sumy) return x;
  51. s[x] = 1ll * s[x] * sumy % mod;
  52. tag[x] = 1ll * tag[x] * sumy % mod;
  53. return x;
  54. }
  55. pushdown(x), pushdown(y);
  56. int o = ++size;
  57. int Lx = (sumx + 1ll * P * s[lc[x]] % mod) % mod;
  58. int Ly = (sumy + 1ll * P * s[lc[y]] % mod) % mod;
  59. int Rx = (sumx + 1ll * (mod + 1 - P) * s[rc[x]] % mod) % mod;
  60. int Ry = (sumy + 1ll * (mod + 1 - P) * s[rc[y]] % mod) % mod;
  61. lc[o] = merge(lc[x], lc[y], Rx, Ry);
  62. rc[o] = merge(rc[x], rc[y], Lx, Ly);
  63. s[o] = (s[lc[o]] + s[rc[o]]) % mod;
  64. return o;
  65. }
  66. inline void getans(int u, int l, int r){
  67. if(l == r) return (void) Ans.push_back(make_pair(l, s[u]));
  68. pushdown(u);
  69. if(lc[u]) getans(lc[u], l, mid);
  70. if(rc[u]) getans(rc[u], mid + 1, r);
  71. }
  72. }
  73. inline int Pow(int a, int b){
  74. int ans = 1;
  75. for(; b; b >>= 1, a = 1ll * a * a % mod)
  76. if(b & 1) ans = 1ll * ans * a % mod;
  77. return ans;
  78. }
  79. inline void dfs(int u){
  80. if(!(int) g[u].size()) Seg::insert(rt[u], 1, M, a[u]);
  81. for(int i = 0; i < (int) g[u].size(); i++){
  82. dfs(g[u][i]);
  83. P = a[u];
  84. rt[u] = Seg::merge(rt[u], rt[g[u][i]], 0, 0);
  85. }
  86. }
  87. int main(){
  88. read(n);
  89. for(int i = 1, x; i <= n; i++) read(x), g[x].push_back(i);
  90. for(int i = 1; i <= n; i++){
  91. read(a[i]);
  92. if((int) g[i].size()) a[i] = 1ll * a[i] * Pow(10000, mod1- 2) % mod;
  93. }
  94. Seg::init();
  95. dfs(1), Seg::getans(rt[1], 1, M), sort(Ans.begin(), Ans.end());
  96. for(int i = 0; i < (int) Ans.size(); i++){
  97. (ans += 1ll * (i + 1) * Ans[i].first % mod * Ans[i].second % mod * Ans[i].second % mod) %= mod;
  98. }
  99. cout << ans << endl;
  100. return 0;
  101. }

loj2538 Slay the Spire

一个显然的贪心策略是从大到小尽可能打出强化牌(至多 \(k-1\) 张),然后从大到小尽可能打出攻击牌。

可以分别对两种牌排序然后按照这个策略设计 dp。

\(f[i][j]\) 表示前 \(i\) 张强化牌摸了 \(j\) 张的期望加成,从大到小对强化牌排序,枚举当前这张牌是否被摸到来转移。

\(g[i][j]\) 表示前 \(i\) 张攻击牌摸了 \(j\) 张的期望攻击力之和,\(j\) 越大可以打的攻击牌越多,所以从小到大排序来转移。

code

  1. /*program by mangoyang*/
  2. #include <bits/stdc++.h>
  3. #define inf (0x7f7f7f7f)
  4. #define Max(a, b) ((a) > (b) ? (a) : (b))
  5. #define Min(a, b) ((a) < (b) ? (a) : (b))
  6. typedef long long ll;
  7. using namespace std;
  8. template <class T>
  9. inline void read(T &x){
  10. int ch = 0, f = 0; x = 0;
  11. for(; !isdigit(ch); ch = getchar()) if(ch == '-') f = 1;
  12. for(; isdigit(ch); ch = getchar()) x = x * 10 + ch - 48;
  13. if(f) x = -x;
  14. }
  15. const int N = 3005, mod = 998244353;
  16. int a[N], b[N], js[N], inv[N], f[2][N], g[2][N], n, m, k;
  17. inline void up(int &x, int y){
  18. x = (x + y >= mod ? x + y - mod : x + y);
  19. }
  20. inline int Pow(int a, int b){
  21. int ans = 1;
  22. for(; b; b >>= 1, a = 1ll * a * a % mod)
  23. if(b & 1) ans = 1ll * ans * a % mod;
  24. return ans;
  25. }
  26. inline int C(int x, int y){
  27. return 1ll * js[x] * inv[y] % mod * inv[x-y] % mod;
  28. }
  29. inline void solve(){
  30. read(n), read(m), read(k);
  31. for(int i = 1; i <= n; i++) read(a[i]);
  32. for(int i = 1; i <= n; i++) read(b[i]);
  33. sort(a + 1, a + n + 1, greater<int>());
  34. sort(b + 1, b + n + 1);
  35. for(int i = 0; i <= n; i++)
  36. f[0][i] = f[1][i] = g[0][i] = g[1][i] = 0;
  37. f[0][0] = 1;
  38. for(int i = 1, o = 1; i <= n; i++, o ^= 1){
  39. for(int j = 0; j <= i; j++){
  40. f[o][j] = f[o^1][j];
  41. if(j && j < k) up(f[o][j], 1ll * a[i] * f[o^1][j-1] % mod);
  42. else if(j) up(f[o][j], f[o^1][j-1]);
  43. }
  44. }
  45. for(int i = 1, o = 1; i <= n; i++, o ^= 1){
  46. for(int j = 0; j <= i; j++){
  47. g[o][j] = g[o^1][j];
  48. if(j){
  49. if(m - j < k - 1) up(g[o][j], g[o^1][j-1]);
  50. up(g[o][j], 1ll * C(i - 1, j - 1) * b[i] % mod);
  51. }
  52. }
  53. }
  54. int ans = 0;
  55. for(int i = 0; i <= min(m, n); i++)
  56. if(m - i <= n) up(ans, 1ll * f[n&1][i] * g[n&1][m-i] % mod);
  57. printf("%d\n", ans);
  58. }
  59. int main(){
  60. js[0] = inv[0] = 1;
  61. for(int i = 1; i < N; i++)
  62. js[i] = 1ll * js[i-1] * i % mod, inv[i] = Pow(js[i], mod - 2);
  63. int T; read(T); while(T--) solve();
  64. return 0;
  65. }

loj2540 随机算法

直接状压 \(dp\) 是 \(O(3^nn)\) 的,实际上选了会冲突的点与已经选了的点显然可以看做同一类点,然后就 \(O(2^nn)\) 了。

code

  1. /*program by mangoyang*/
  2. #include<bits/stdc++.h>
  3. #define inf (0x7f7f7f7f)
  4. #define Max(a, b) ((a) > (b) ? (a) : (b))
  5. #define Min(a, b) ((a) < (b) ? (a) : (b))
  6. typedef long long ll;
  7. using namespace std;
  8. template <class T>
  9. inline void read(T &x){
  10. int ch = 0, f = 0; x = 0;
  11. for(; !isdigit(ch); ch = getchar()) if(ch == '-') f = 1;
  12. for(; isdigit(ch); ch = getchar()) x = x * 10 + ch - 48;
  13. if(f) x = -x;
  14. }
  15. const int mod = 998244353;
  16. int cnt[1<<21], dp[1<<21][21], js[21], inv[21], ed[21], n, m;
  17. inline int Pow(int a, int b){
  18. int ans = 1;
  19. for(; b; b >>= 1, a = 1ll * a * a % mod)
  20. if(b & 1) ans = 1ll * ans * a % mod;
  21. return ans;
  22. }
  23. inline int A(int x, int y){
  24. return 1ll * js[x] * inv[x-y] % mod;
  25. }
  26. inline void up(int &x, int y){
  27. x = (x + y >= mod ? x + y - mod : x + y);
  28. }
  29. int main(){
  30. read(n), read(m);
  31. js[0] = inv[0] = 1;
  32. for(int i = 1; i <= n; i++){
  33. js[i] = 1ll * js[i-1] * i % mod;
  34. inv[i] = Pow(js[i], mod - 2);
  35. }
  36. for(int i = 1, x, y; i <= m; i++){
  37. read(x), read(y);
  38. ed[x] |= 1 << (y - 1);
  39. ed[y] |= 1 << (x - 1);
  40. }
  41. for(int s = 0; s < (1 << n); s++)
  42. for(int i = 0; i < n; i++)
  43. if((1 << i) & s) cnt[s]++;
  44. dp[0][0] = 1;
  45. for(int s = 0; s < (1 << n) - 1; s++)
  46. for(int i = 0; i < n; i++) if(dp[s][i]){
  47. for(int j = 0; j < n; j++) if(!((1 << j) & s)){
  48. int t = s | (1 << j) | ed[j+1];
  49. up(dp[t][i+1], 1ll * dp[s][i] * A(n - cnt[s] - 1, cnt[s^t] - 1) % mod);
  50. }
  51. }
  52. int mx = 0;
  53. for(int i = 1; i <= n; i++) if(dp[(1<<n)-1][i]) mx = i;
  54. cout << 1ll * dp[(1<<n)-1][mx] * inv[n] % mod << endl;
  55. return 0;
  56. }

loj2542 随机游走

设 \(dp[x][s]\) 为从 \(x\) 出发走到点集 \(s\) 中任意一个点的期望步数,然后 \(\min-\max\) 容斥即可 ,直接分层图+高斯消元跑不过去,可以用小套路把未知数设出来以后每个点都可以用其父亲的答案乘上一个系数再加上一个常数来表示,然后跑一遍树形dp就做完了。

code

  1. /*program by mangoyang*/
  2. #include<bits/stdc++.h>
  3. #define inf (0x7f7f7f7f)
  4. #define Max(a, b) ((a) > (b) ? (a) : (b))
  5. #define Min(a, b) ((a) < (b) ? (a) : (b))
  6. typedef long long ll;
  7. using namespace std;
  8. template <class T>
  9. inline void read(T &x){
  10. int ch = 0, f = 0; x = 0;
  11. for(; !isdigit(ch); ch = getchar()) if(ch == '-') f = 1;
  12. for(; isdigit(ch); ch = getchar()) x = x * 10 + ch - 48;
  13. if(f) x = -x;
  14. }
  15. const int N = 1 << 21, mod = 998244353;
  16. vector<int> g[N];
  17. int mn[N], cnt[N], in[N], A[N], B[N], n, q, rt;
  18. inline int Pow(int a, int b){
  19. int ans = 1;
  20. for(; b; b >>= 1, a = 1ll * a * a % mod)
  21. if(b & 1) ans = 1ll * ans * a % mod;
  22. return ans;
  23. }
  24. inline void dfs(int u, int fa){
  25. if(in[u]) return (void) (A[u] = B[u] = 0);
  26. int SA = 0, SB = 0, deg = (int) g[u].size();
  27. for(int i = 0; i < (int) g[u].size(); i++){
  28. int v = g[u][i];
  29. if(v == fa) continue;
  30. dfs(v, u);
  31. SA = (SA + A[v]) % mod, SB = (SB + B[v]) % mod;
  32. }
  33. deg = Pow(deg, mod - 2);
  34. int x = (1 - 1ll * SA * deg % mod + mod) % mod;
  35. x = Pow(x, mod - 2);
  36. A[u] = 1ll * deg * x % mod;
  37. B[u] = 1ll * x * (1ll * SB * deg % mod + 1) % mod;
  38. }
  39. int main(){
  40. read(n), read(q), read(rt);
  41. for(int i = 1, x, y; i < n; i++){
  42. read(x), read(y);
  43. g[x].push_back(y), g[y].push_back(x);
  44. }
  45. for(int s = 0; s < (1 << n); s++){
  46. for(int i = 1; i <= n; i++){
  47. in[i] = ((1 << (i - 1)) & s) ? 1 : 0;
  48. cnt[s] += in[i];
  49. }
  50. dfs(rt, 0), mn[s] = B[rt];
  51. }
  52. while(q--){
  53. int num, sta = 0;
  54. read(num);
  55. for(int i = 1, x; i <= num; i++) read(x), sta |= 1 << (x - 1);
  56. int ans = 0;
  57. for(int s = sta; s; s = (s - 1) & sta)
  58. (ans += 1ll * ((cnt[s] & 1) ? 1 : mod - 1) * mn[s] % mod) %= mod;
  59. printf("%d\n", ans);
  60. }
  61. return 0;
  62. }

loj6432 真实排名

对于每个点枚举一下要不要,统计一下会影响的人数,组合数算一下就好了

code

  1. /*program by mangoyang*/
  2. #include <bits/stdc++.h>
  3. #define inf (0x7f7f7f7f)
  4. #define Max(a, b) ((a) > (b) ? (a) : (b))
  5. #define Min(a, b) ((a) < (b) ? (a) : (b))
  6. typedef long long ll;
  7. using namespace std;
  8. template <class T>
  9. inline void read(T &x){
  10. int ch = 0, f = 0; x = 0;
  11. for(; !isdigit(ch); ch = getchar()) if(ch == '-') f = 1;
  12. for(; isdigit(ch); ch = getchar()) x = x * 10 + ch - 48;
  13. if(f) x = -x;
  14. }
  15. #define fi first
  16. #define se second
  17. const int N = 1000005, mod = 998244353;
  18. pair<int, int> a[N];
  19. int js[N], inv[N], ans[N], n, k;
  20. inline int Pow(int a, int b){
  21. int ans = 1;
  22. for(; b; b >>= 1, a = 1ll * a * a % mod)
  23. if(b & 1) ans = 1ll * ans * a % mod;
  24. return ans;
  25. }
  26. inline int C(int x, int y){
  27. if(x < y || x < 0 || y < 0) return 0;
  28. return 1ll * js[x] * inv[y] % mod * inv[x-y] % mod;
  29. }
  30. int main(){
  31. read(n), read(k);
  32. js[0] = inv[0] = 1;
  33. for(int i = 1; i <= n; i++){
  34. js[i] = 1ll * js[i-1] * i % mod;
  35. inv[i] = Pow(js[i], mod - 2);
  36. read(a[i].fi), a[i].se = i;
  37. }
  38. sort(a + 1, a + n + 1);
  39. int p = 0, q = 0;
  40. for(int i = 1; i <= n; i++){
  41. if(a[i].fi == a[i-1].fi && i > 1){
  42. ans[a[i].se] = ans[a[i-1].se];
  43. continue;
  44. }
  45. while(a[p+1].fi * 2 < a[i].fi && p < n) p++;
  46. while(a[q+1].fi < a[i].fi * 2 && q < n) q++;
  47. int tot1 = i - p - 1, tot2 = max(q, i) - i + 1;
  48. (ans[a[i].se] += C(n - tot1 - 1, k)) %= mod;
  49. (ans[a[i].se] += C(n - tot2, k - tot2)) %= mod;
  50. }
  51. for(int i = 1; i <= n; i++) printf("%d\n", ans[i]);
  52. return 0;
  53. }

loj6433 最大前缀和

考虑每一个集合成为最大前缀和的方案数,这个等于其内部排列满足全部选是最大前缀和乘上剩余元素无论怎么排都不存在一个前缀和 \(>0\) 的方案数,两部分分开来状压 \(dp\) 即可。

code

  1. /*program by mangoyang*/
  2. #include <bits/stdc++.h>
  3. #define inf (0x7f7f7f7f)
  4. #define Max(a, b) ((a) > (b) ? (a) : (b))
  5. #define Min(a, b) ((a) < (b) ? (a) : (b))
  6. typedef long long ll;
  7. using namespace std;
  8. template <class T>
  9. inline void read(T &x){
  10. int ch = 0, f = 0; x = 0;
  11. for(; !isdigit(ch); ch = getchar()) if(ch == '-') f = 1;
  12. for(; isdigit(ch); ch = getchar()) x = x * 10 + ch - 48;
  13. if(f) x = -x;
  14. }
  15. const int N = (1 << 20), mod = 998244353;
  16. int a[N], f[N], sum[N], g[N], n;
  17. inline void up(int &x, int y){
  18. x = x + y >= mod ? x + y - mod : x + y;
  19. }
  20. int main(){
  21. read(n);
  22. for(int i = 1; i <= n; i++) read(a[i]);
  23. for(int s = 1; s < (1 << n); s++)
  24. for(int i = 0; i < n; i++)
  25. if((1 << i) & s) sum[s] += a[i+1];
  26. g[0] = 1;
  27. for(int i = 0; i < n; i++) f[1<<i] = 1;
  28. for(int s = 0; s < (1 << n); s++)
  29. for(int i = 0; i < n; i++) if(!((1 << i) & s)){
  30. int t = s ^ (1 << i);
  31. if(sum[s] > 0) up(f[t], f[s]);
  32. if(sum[t] <= 0) up(g[t], g[s]);
  33. }
  34. int ans = 0;
  35. for(int s = 0; s < (1 << n); s++){
  36. sum[s] = (sum[s] % mod + mod) % mod;
  37. up(ans, 1ll * sum[s] * f[s] % mod * g[((1<<n)-1)^s] % mod);
  38. }
  39. cout << ans << endl;
  40. return 0;
  41. }

loj6436 星际穿越

可以发现每个点出发最多会向右走一步,于是倍增出每个点走 \(2^j\) 步能走到的最左端点,已经走到这之间所有点的距离和,每次询问拆成两个以 \(x\) 结尾的后缀来询问即可。

code

  1. /*program by mangoyang*/
  2. #include <bits/stdc++.h>
  3. #define inf (0x7f7f7f7f)
  4. #define Max(a, b) ((a) > (b) ? (a) : (b))
  5. #define Min(a, b) ((a) < (b) ? (a) : (b))
  6. typedef long long ll;
  7. using namespace std;
  8. template <class T>
  9. inline void read(T &x){
  10. int ch = 0, f = 0; x = 0;
  11. for(; !isdigit(ch); ch = getchar()) if(ch == '-') f = 1;
  12. for(; isdigit(ch); ch = getchar()) x = x * 10 + ch - 48;
  13. if(f) x = -x;
  14. }
  15. const int N = 300005;
  16. ll a[N], f[N][21], s[N][21];
  17. int n, q;
  18. inline ll calc(int x, int L){
  19. if(a[x] <= L) return x - L;
  20. ll ans = x - a[x], now = 1; x = a[x];
  21. for(int i = 20; ~i; i--) if(f[x][i] >= L){
  22. ans += s[x][i] + (x - f[x][i]) * now;
  23. now += 1 << i, x = f[x][i];
  24. }
  25. return ans + (x - L) * (now + 1);
  26. }
  27. int main(){
  28. read(n), a[1] = 1;
  29. for(int i = 2; i <= n; i++) read(a[i]);
  30. for(int i = n; i >= 1; i--){
  31. f[i][0] = min(a[i], i == n ? inf : f[i+1][0]);
  32. s[i][0] = i - f[i][0];
  33. }
  34. for(int j = 1; j <= 20; j++)
  35. for(int i = 1; i <= n; i++){
  36. f[i][j] = f[f[i][j-1]][j-1];
  37. s[i][j] = s[i][j-1] + s[f[i][j-1]][j-1];
  38. s[i][j] += (f[i][j-1] - f[f[i][j-1]][j-1]) << (j - 1);
  39. }
  40. read(q);
  41. for(int i = 1, l, r, x; i <= q; i++){
  42. read(l), read(r), read(x);
  43. ll ans = calc(x, l) - calc(x, r + 1);
  44. ll g = __gcd(ans, (ll) r - l + 1);
  45. printf("%lld/%lld\n", ans / g, (r - l + 1) / g);
  46. }
  47. return 0;
  48. }

loj6436 神仙的游戏

border有关的计数题可以从等差数列和周期两个角度考虑,这个题显然不能等差数列于是就直接上周期定理。

套用周期定理得到如果 \(i\) 是一个 border,那么所有模 \(|S|-i\) 同余的位置必须相同,也就是不能出现两个距离为 \(|S|-i-1\) 的 \(0,1\) 位置,直接用 FTT 统计所有差的信息即可。

code

  1. /*program by mangoyang*/
  2. #include <bits/stdc++.h>
  3. #define inf (0x7f7f7f7f)
  4. #define Max(a, b) ((a) > (b) ? (a) : (b))
  5. #define Min(a, b) ((a) < (b) ? (a) : (b))
  6. typedef long long ll;
  7. using namespace std;
  8. template <class T>
  9. inline void read(T &x){
  10. int ch = 0, f = 0; x = 0;
  11. for(; !isdigit(ch); ch = getchar()) if(ch == '-') f = 1;
  12. for(; isdigit(ch); ch = getchar()) x = x * 10 + ch - 48;
  13. if(f) x = -x;
  14. }
  15. const int N = (1 << 22), P = 998244353, G = 3;
  16. char s[N];
  17. int a[N], b[N];
  18. namespace poly{
  19. int rev[N], lg, len;
  20. inline int Pow(int a, int b){
  21. int ans = 1;
  22. for(; b; b >>= 1, a = 1ll * a * a % P)
  23. if(b & 1) ans = 1ll * ans * a % P;
  24. return ans;
  25. }
  26. inline void timesinit(int lenth){
  27. for(len = 1, lg = 0; len <= lenth; len <<= 1, lg++);
  28. for(int i = 0; i < len; i++)
  29. rev[i] = (rev[i>>1] >> 1) | ((i & 1) << (lg - 1));
  30. }
  31. inline void dft(int *a, int sgn){
  32. for(int i = 0; i < len; i++)
  33. if(i < rev[i]) swap(a[i], a[rev[i]]);
  34. for(int k = 2; k <= len; k <<= 1){
  35. int w = Pow(G, (P - 1) / k);
  36. if(sgn == - 1) w = Pow(w, P - 2);
  37. for(int i = 0; i < len; i += k){
  38. int now = 1;
  39. for(int j = i; j < i + (k >> 1); j++){
  40. int x = a[j], y = 1ll * a[j+(k>>1)] * now % P;
  41. a[j] = x + y >= P ? x + y - P : x + y;
  42. a[j+(k>>1)] = x - y < 0 ? x - y + P : x - y;
  43. now = 1ll * now * w % P;
  44. }
  45. }
  46. }
  47. if(sgn == -1){
  48. int Inv = Pow(len, P - 2);
  49. for(int i = 0; i < len; i++)
  50. a[i] = 1ll * a[i] * Inv % P;
  51. }
  52. }
  53. }
  54. using poly::timesinit;
  55. using poly::dft;
  56. int main(){
  57. scanf("%s", s); int n = strlen(s);
  58. for(int i = 0; i < n; i++)
  59. a[i] = s[i] == '0', b[i] = s[i] == '1';
  60. reverse(b, b + n);
  61. timesinit(n + n - 1);
  62. dft(a, 1), dft(b, 1);
  63. for(int i = 0; i < poly::len; i++)
  64. a[i] = 1ll * a[i] * b[i] % P;
  65. dft(a, -1);
  66. ll ans = 1ll * n * n;
  67. for(int i = 1; i < n; i++){
  68. int flag = 0;
  69. for(int j = i; j < n; j += i)
  70. if(a[n-1+j] || a[n-1-j]) flag = 1;
  71. if(!flag) ans ^= 1ll * (n - i) * (n - i);
  72. }
  73. cout << ans << endl;
  74. return 0;
  75. }

「PKUWC2018/PKUSC2018」试题选做的更多相关文章

  1. 「美团 CodeM 初赛 Round A」试题泛做

    最长树链 树形DP.我们发现gcd是多少其实并不重要,只要不是1就好了,此外只要有一个公共的质数就好了.计f[i][j]表示i子树内含有j因子的最长链是多少.因为一个数的不同的质因子个数是log级别的 ...

  2. 「美团 CodeM 资格赛」试题泛做

    LibreOJ真是吼啊! 数码 推个式子,把枚举因数转为枚举倍数.然后就发现它是根号分段的.然后每一段算一下就好了. #include <cstdio> #include <cstr ...

  3. CSP-J/S2019试题选做

    S D1T2 括号树 设\(f[u]\)表示根到\(u\)的路径上有多少子串是合法括号串.(即题目里的\(k_u\),此变量名缺乏个性,故换之) 从根向每个节点dfs,容易求出\(c[u]\):表示从 ...

  4. LOJ 2991 「THUSC 2016」补退选——trie+线段树合并或vector

    题目:https://loj.ac/problem/2291 想了线段树合并的做法.就是用线段树维护 trie 的每个点在各种时间的操作. 然后线段树合并一番,线段树维护前缀最大值,就是维护最大子段和 ...

  5. loj2291 「THUSC 2016」补退选

    ref pkusc 快到了,做点 thusc 的题涨涨 rp-- #include <iostream> #include <cstring> #include <cst ...

  6. 「刷题」THUPC泛做

    刷了一下,写一下. T1. 天天爱射击 可以这样想. 我们二分一下每一块木板在什么时刻被击碎. 然后直接用主席树维护的话是\(O(nlog^2n)\)的. 会\(T\),而且是一分不给那种... 那么 ...

  7. 【LOJ】#2291. 「THUSC 2016」补退选

    题解 在trie树上开vector记录一下这个前缀出现次数第一次达到某个值的下标,以及记录一下现在这个前缀有多少个 为什么thusc有那么水的题--是为了防我这种cai ji爆零么= = 代码 #in ...

  8. 微服务架构之「 API网关 」

    在微服务架构的系列文章中,前面已经通过文章<架构设计之「服务注册 」>介绍过了服务注册的原理和应用,今天这篇文章我们来聊一聊「 API网关 」. 「 API网关 」是任何微服务架构的重要组 ...

  9. 「LOJ2000~2023」各省省选题选做

    「LOJ2000~2023」各省省选题选做 「SDOI2017」数字表格 莫比乌斯反演. 「SDOI2017」树点涂色 咕咕咕. 「SDOI2017」序列计数 多项式快速幂. 我们将超过 \(p\) ...

随机推荐

  1. err Invalid input of type: 'dict'. Convert to a byte, string or number first

    一个问题引发的血案: 用python向redis写入数据报错: redis.exceptions.DataError: Invalid input of type: 'dict'. Convert t ...

  2. 廖雪峰Python笔记

    △命令行模式和Python交互模式 在Windows开始菜单选择“命令提示符”,就进入到命令行模式,它的提示符类似C:\>:在命令行模式下敲命令python,就看到类似如下的一堆文本输出,然后就 ...

  3. (4.1)打造简单OS-小实验[图形显示]

    主要是实现<简单打造OS>第四小节说到的一个图形界面的实验项目 1.mbr boot.inc ;------------- loader和kernel ---------- LOADER_ ...

  4. TCP的连接如何知道对方已经异常断开

    断电的话,对方不会发送任何数据包过来,包括RST.主机无法得知.如果是TCP已经连接,有个定时器,会发送空包,sequence number不变.如果一直收不到ack,会断定对方已经无法通信,而释放系 ...

  5. nacos-server安装、运行 (docker)

    https://nacos.io/en-us/docs/quick-start-docker.htmlhttps://github.com/nacos-group/nacos-docker mkdir ...

  6. [转]vue项目中 指令 v-html 中使用过滤器filters功能

    转载于简书 链接:http://www.jianshu.com/p/29b7eaabd1ba 问题 2.0 filters only work in mustache tags and v-bind. ...

  7. BUG处理流程图

    流程描述: 1. 测试人员发现bug提交给开发. 2. 开发人员判断是否是bug. 3. 如果是bug,进行修改,修改完成后更改bug状态为已解决. 4. 如果不是bug,退回给测试人员并描述退回原因 ...

  8. C#对泛型实例化对像的方法

    最近在搞一个小东东,用到了泛型的处理,用到了对泛型的实例化问题.下面来讲讲对泛型的实例化,以代码为例,如: public class A { } public class B<T> { p ...

  9. [LeetCode] 441. Arranging Coins 排列硬币

    You have a total of n coins that you want to form in a staircase shape, where every k-th row must ha ...

  10. sql多列值一行显示

    select stuff(( select ',' + UserNM from tblSysUser for xml path('')), 1,1,'')