[关闭]
@Falsyta 2015-08-09T05:11:25.000000Z 字数 6302 阅读 1394

mxh带窝打多校之Contest 5

OI mxh带窝飞


约定

对于两个字符串a,bab表示ab首尾相接得到的串。
对于两个字符串s,SsS表示sS的子串。

题意

mxh Round www

1001 MZL's Circle Zhou

给出两个串ST,问本质不同的st(sS,tT)有多少种。

1002 MZL's XOR

给出A,求{Ai+Aj|1i,jN}的异或和。

1004 MZL's game

N个格子,初始全为白,每一轮选一个白格子染灰,其他每个白格子有p的概率被染黑,若无白格子就停止,对于1kN,求一个白格子在第k轮被染灰的概率。

1006 MZL's endless loop

对于给定的无向图G={V,E},请为每条边确定一个方向,使得对于任意一点x,有|inxoutx|1

1007 MZL's simple problem

维护一个多重集S,支持:
1. 向S插入元素x
2. 删除最小元素
3. 询问最大元素

1008 MZL's manhuff function

给出长度为N的数列A,令

Bi=j=iNAi

f(i,j)=0min(f(i1,j+1),f(i,j2)+Bi)1011037(i,j)=(1,1)i,j[1,n], (i,j)(1,1)otherwise

f(n,1)

1009 MZL's Border

F是字符串序列。

F1=b
F2=a
Fn=Fn1Fn2(n>2)

其中Fn1Fn2是拼接Fn1Fn2
S=FN[1M]

max{S[1i]=S[|S|i+1|S|]|i<|S|}

题解

1001 MZL's Circle Zhou

考虑对每个串s确定唯一的分割方式,即若能在S中找到子串则记为(s,""),否则令s0sS的SAM中的最大匹配部分,其余部分记作s2,则将其记为(s1,s2)
显然地,对于s1,若s1cS中没有出现,则所有T中以c开头的子串s2都是合法的。
在SAM上DP即可。
别忘了unsigned long long QAQ

  1. # include <cstdio>
  2. # include <cstring>
  3. # define REP(i, n) for (int i = 1; i <= n; i ++)
  4. # define REP_0(i, n) for (int i = 0; i < n; i ++)
  5. # define REP_0N(i, n) for (int i = 0; i <= n; i ++)
  6. # define REP_D(i, n) for (int i = n; i >= 1; i --)
  7. # define CLR(a, x) memset (a, x, sizeof (a))
  8. typedef unsigned long long ll;
  9. const int NR = 100100;
  10. struct Sam {int trans[26], par, l; Sam () {CLR (trans, -1);}} sam[NR << 1];
  11. int d[NR << 1], cnt[NR], lst, sz, q0;
  12. ll f[NR << 1], g[NR << 1], res[30];
  13. char s0[NR], s1[NR];
  14. # define u sam[x]
  15. # define v u.trans[c]
  16. # define vn sam[v]
  17. # define o sam[y]
  18. # define w sam[z]
  19. inline void Init () {REP (x, sz) CLR (u.trans, -1); sam[sz = lst = 1].par = -1;}
  20. void AddChar (int c)
  21. {
  22. int x = lst, z = ++ sz; lst = z, w.l = u.l + 1;
  23. for (; x != -1 && v == -1; x = u.par) v = z;
  24. if (x == -1) w.par = 1;
  25. else if (u.l + 1 == vn.l) w.par = v;
  26. else
  27. {
  28. int y = ++ sz, tv = v;
  29. o = vn, o.l = u.l + 1, w.par = vn.par = y;
  30. for (; x != -1 && v == tv; x = u.par) v = y;
  31. }
  32. }
  33. void Sort (int len)
  34. {
  35. REP_0N (i, len) cnt[i] = 0;
  36. REP (x, sz) cnt[u.l] ++;
  37. REP (i, len) cnt[i] += cnt[i - 1];
  38. REP (x, sz) d[cnt[u.l] --] = x;
  39. }
  40. int main ()
  41. {
  42. for (scanf ("%d", &q0); q0; q0 --)
  43. {
  44. scanf ("%s%s", s0 + 1, s1 + 1);
  45. int l0 = strlen (s0 + 1), l1 = strlen (s1 + 1);
  46. Init (); REP (i, l1) AddChar (s1[i] - 'a'); Sort (l1);
  47. REP_D (i, sz)
  48. {
  49. int x = d[i]; g[x] = 1;
  50. REP_0 (c, 26) if (v != -1) g[x] += g[v];
  51. }
  52. {int x = 1; REP_0 (c, 26) v != -1 ? res[c] = g[v] : res[c] = 0;}
  53. Init (); REP (i, l0) AddChar (s0[i] - 'a'); Sort (l0);
  54. REP (x, sz) f[x] = (u.par == -1 ? 1 : (u.l - sam[u.par].l));
  55. REP_D (i, sz)
  56. {
  57. int x = d[i];
  58. REP_0 (c, 26) if (v == -1) f[x] += res[c] * (u.par == -1 ? 1 : (u.l - sam[u.par].l));
  59. if (u.par != -1) f[u.par] += f[x];
  60. }
  61. printf ("%llu\n", f[1]);
  62. }
  63. return 0;
  64. }

1002 MZL's XOR

注意到1i,jN,所以对于ij的贡献都是0。

  1. # include <cstdio>
  2. int main ()
  3. {
  4. int q0, n, m, z, l;
  5. for (scanf ("%d", &q0); q0; q0 --)
  6. {
  7. scanf ("%d%d%d%d", &n, &m, &z, &l);
  8. int res = 0, a = 0;
  9. for (int i = 2; i <= n; i ++) a = (1ll * a * m + z) % l, res ^= (a << 1);
  10. printf ("%d\n", res);
  11. }
  12. return 0;
  13. }

1004 MZL‘s game

考虑编号从小到大染灰。
F(i,j)为第j轮时第i个格子之前全为有色格子的概率。
F(i,j)=(1p)jF(i1,j1)+(1(1p)j)F(i1,j)

1006 MZL's endless loop

考虑一个环,做法是显然的。
把所有环删掉以后原图变为森林。
在树上DFS一遍显然可以定向。

  1. # include <cstdio>
  2. # include <cstring>
  3. # include <cassert>
  4. # include <algorithm>
  5. # include <iostream>
  6. # define REP(i, n) for (int i = 1; i <= n; i ++)
  7. # define REP_G(i, x) for (int i = pos[x]; i; i = g[i].f)
  8. # define RST(a) memset (a, 0, sizeof (a))
  9. using namespace std;
  10. const int NR = 100100, ER = 300100;
  11. int q0, n, m, gsz, top, f[NR], pos[NR], stk[NR], cur[NR], pre[NR];
  12. bool vis[NR], col[ER], del[ER];
  13. struct Edge {int y, f; void Set (int yr, int fr) {y = yr, f = fr;}} g[ER << 1];
  14. void AE (int x, int y) {g[++ gsz].Set (y, pos[x]), pos[x] = gsz;}
  15. # define v g[i].y
  16. void DFS (int S)
  17. {
  18. vis[stk[top = 1] = S] = 1;
  19. while (top)
  20. {
  21. int x = stk[top]; bool EXIT = 0;
  22. for (int &i = cur[x]; i; i = g[i].f)
  23. {
  24. if ((pre[x] ^ 1) == i || del[i >> 1]) continue;
  25. if (vis[v])
  26. {
  27. del[i >> 1] = 1, col[i >> 1] = (i & 1);
  28. for (; stk[top] != v; top --) del[pre[stk[top]] >> 1] = 1, col[pre[stk[top]] >> 1] = (pre[stk[top]] & 1), vis[stk[top]] = 0;
  29. i = g[i].f;
  30. EXIT = 1; break;
  31. }
  32. else {vis[stk[++ top] = v] = 1; pre[v] = i, i = g[i].f; EXIT = 1; break;}
  33. }
  34. if (!EXIT) vis[x] = 0, top --;
  35. }
  36. }
  37. void Calc (int x)
  38. {
  39. vis[x] = 1;
  40. REP_G (i, x)
  41. if (!vis[v] && !del[i >> 1])
  42. {
  43. if (!f[x]) f[x] = 1, f[v] = -1, col[i >> 1] = (i & 1), Calc (v);
  44. else col[i >> 1] = ((f[x] == 1) ^ (i & 1)), f[v] = f[x], f[x] = 0, Calc (v);
  45. }
  46. }
  47. int main ()
  48. {
  49. for (scanf ("%d", &q0); q0; q0 --)
  50. {
  51. scanf ("%d%d", &n, &m), gsz = 1; int t1, t2;
  52. RST (f), RST (col), RST (vis), RST (del), RST (pos);
  53. REP (i, m)
  54. {
  55. scanf ("%d%d", &t1, &t2);
  56. if (t1 == t2) gsz += 2;
  57. else AE (t1, t2), AE (t2, t1);
  58. }
  59. REP (i, n) cur[i] = pos[i];
  60. REP (i, n) DFS (i);
  61. REP (i, n) if (!vis[i]) Calc (i);
  62. REP (i, m) printf ("%d\n", col[i]);
  63. }
  64. return 0;
  65. }

1007 MZL's simple problem

维护最大值和当前集合大小。

1008 MZL's manhuff function

考虑题目和哈夫曼树有关。
原函数的意义是添加到位置i现在有j棵树需要合并时的最小代价。
用哈夫曼树求得的解显然是最优的。

  1. # include <cstdio>
  2. # include <queue>
  3. # define REP(i, n) for (int i = 1; i <= n; i ++)
  4. using namespace std;
  5. priority_queue <long long> Q;
  6. int main ()
  7. {
  8. int q0;
  9. for (scanf ("%d", &q0); q0; q0 --)
  10. {
  11. int ta, n;
  12. scanf ("%d", &n);
  13. REP (i, n) scanf ("%d", &ta), Q.push (- ta);
  14. long long ans = 0;
  15. while (1)
  16. {
  17. int w0 = - Q.top (), w1; Q.pop ();
  18. if (Q.empty ()) break;
  19. w1 = - Q.top (); Q.pop ();
  20. ans += w0 + w1, Q.push (- w0 - w1);
  21. }
  22. printf ("%I64d\n", ans);
  23. }
  24. return 0;
  25. }

1009 MZL's Border

打表,不会证。

  1. # include <cstdio>
  2. # include <cstring>
  3. # include <algorithm>
  4. # include <iostream>
  5. # define REP(i, n) for (int i = 1; i <= n; i ++)
  6. # define REP_0(i, n) for (int i = 0; i < n; i ++)
  7. # define REP_D0(i, n) for (int i = n - 1; i >= 0; i --)
  8. # define FOR(i, a, b) for (int i = a; i <= b; i ++)
  9. # define RST(a) memset (a, 0, sizeof (a))
  10. using namespace std;
  11. const int NR = 10000;
  12. const int P = 258280327;
  13. const int W = 100000000;
  14. int poolA[NR], la, poolB[NR], lb, poolC[NR], lc;
  15. int f[20000];
  16. bool Comp (int *a, int *b, int la, int lb)
  17. {
  18. if (la > lb) return 1;
  19. if (la < lb) return 0;
  20. REP_D0 (i, la)
  21. {
  22. if (a[i] > b[i]) return 1;
  23. if (a[i] < b[i]) return 0;
  24. }
  25. return 0;
  26. }
  27. void Minus (int *a, int *b, int &la, int lb)
  28. {
  29. REP_0 (i, lb)
  30. {
  31. a[i] -= b[i];
  32. if (a[i] < 0)
  33. {
  34. a[i] += W, a[i + 1] --;
  35. if (i + 1 == lb) lb ++;
  36. }
  37. }
  38. if (la == lb) while (!a[la - 1]) la --;
  39. }
  40. void Add (int *a, int *b, int &la, int lb)
  41. {
  42. REP_0 (i, lb)
  43. {
  44. a[i] += b[i];
  45. if (a[i] >= W)
  46. {
  47. a[i] -= W, a[i + 1] ++;
  48. if (i + 1 == lb) lb ++;
  49. }
  50. }
  51. if (lb > la) la = lb;
  52. }
  53. char s[2000];
  54. int main ()
  55. {
  56. int q0, n; f[0] = 0, f[1] = 1;
  57. FOR (i, 2, 15000)
  58. {
  59. f[i] = f[i - 1] + f[i - 2];
  60. if (f[i] >= P) f[i] -= P;
  61. }
  62. for (scanf ("%d", &q0); q0; q0 --)
  63. {
  64. scanf ("%d%s", &n, s), RST (poolA), RST (poolB), RST (poolC);
  65. int len = strlen (s);
  66. REP_0 (i, len) if (i < len - i - 1) swap (s[len - i - 1], s[i]);
  67. if (n < 3) {printf ("%d\n", 0); continue;}
  68. la = lb = lc = 0;
  69. int *a = poolA, *b = poolB, *c = poolC, tW = 0;
  70. REP_D0 (i, len)
  71. {
  72. tW = 1ll * tW * 10 + s[i] - '0';
  73. if (!(i % 8)) a[la ++] = tW, tW = 0;
  74. }
  75. REP_0 (i, la) if (i < la - i - 1) swap (a[la - i - 1], a[i]);
  76. int cur = 0, lev = 0, aw = 0;
  77. lb = lc = b[0] = c[0] = 1;
  78. while (Comp (a, b, la, lb))
  79. {
  80. Minus (a, b, la, lb), Add (c, b, lc, lb);
  81. swap (b, c), swap (lb, lc);
  82. cur += f[lev ++]; if (cur >= P) cur -= P;
  83. }
  84. REP_D0 (i, la) aw = (1ll * W * aw + a[i]) % P;
  85. cur += aw - 1; if (cur >= P) cur -= P;
  86. printf ("%d\n", cur);
  87. }
  88. return 0;
  89. }
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注