diff --git a/README.md b/README.md index 249122f52..7d58fec82 100644 --- a/README.md +++ b/README.md @@ -76,8 +76,8 @@ Live2D的后端暂时使用了[fghrsh](https://www.fghrsh.net/post/170.html)提 >

章北海感到父亲的灵魂从冥冥中降落到飞船上,与他融为一体,他按动了操作界面上那个最后的按钮,心中默念出那个他用尽一生的努力所追求的指令:

“‘自然选择’,前进四!”

## 历程 -### 2019-04-12 v2.1.3 -页面样式微调,将masthead调矮 +### 2019-04-29 v2.1.3 +页面样式微调,将masthead调矮,将标题字号改小 ### 2019-03-20 v2.1.2 修复sidebar展开时回到顶部的问题 ### 2019-03-18 v2.1.1 diff --git a/_config.yml b/_config.yml index 2c6d9e58a..d3aaceb08 100644 --- a/_config.yml +++ b/_config.yml @@ -95,12 +95,6 @@ head: # 删改前确定知道自己在做什么 value: stylesheet - key: href value: /public/css/lanyon.css - - tag: link - var: - - key: rel - value: stylesheet - - key: href - value: //fonts.loli.net/css?family=PT+Serif:400,400italic,700%7CPT+Sans:400 - tag: link var: - key: rel diff --git a/_layouts/page.html b/_layouts/page.html index 99f486f05..2eb271102 100644 --- a/_layouts/page.html +++ b/_layouts/page.html @@ -36,14 +36,14 @@
-

+

{{ page.title }} {{ site.title }}
-

+
{{ content }}
diff --git a/_posts/2019-04-25-Codeforces Round #554 (Div. 2).md b/_posts/2019-04-25-Codeforces Round #554 (Div. 2).md index dceb65a14..87898c910 100644 --- a/_posts/2019-04-25-Codeforces Round #554 (Div. 2).md +++ b/_posts/2019-04-25-Codeforces Round #554 (Div. 2).md @@ -1,5 +1,5 @@ --- -title: Codeforces Round \#554 (Div. 2) +title: Codeforces Round #554 (Div. 2) categories: - ACM - 题解 @@ -234,3 +234,89 @@ int main() printf("%d ", rk[g.e[g.p[n - 2]].second]); } ``` +# [Neko Rules the Catniverse (Small Version)](https://vjudge.net/problem/CodeForces-1152F1) +状压DP,用$f[i][j][mask]$来表示正在考虑第i个,已经考虑了第$j$个,后$m$个的选择状态是二进制位集$mask$。 + +这里可以滚动数组。 +```cpp +#include +using namespace std; +void add(int &a, long long b, int M = 1e9 + 7) { a = (a + b) % M; } +int n, k, m; +int main() +{ + scanf("%d%d%d", &n, &k, &m); + vector> f(k + 1, vector(1 << m, 0)); + f[0][0] = 1; + for (int i = 0; i < n; ++i) + { + vector> g(k + 1, vector(1 << m, 0)); + for (int j = 0; j < f.size(); ++j) + for (int mask = 0; mask < f[j].size(); ++mask) + { + int newMask = (mask << 1) % f[j].size(); + add(g[j][newMask], f[j][mask]); + if (j < k) + add(g[j + 1][newMask | 1], (1LL + __builtin_popcount(mask)) * f[j][mask]); + } + f.swap(g); + } + for (int mask = m = 0; mask < f[k].size(); ++mask) + add(m, f[k][mask]); + printf("%d", m); +} +``` +# [Neko Rules the Catniverse (Large Version)](https://vjudge.net/problem/CodeForces-1152F2) +注意到状态只在相邻的两位转移,这里可以用矩阵加速DP。 + +下面这段代码跑了5070ms,官方还有一个[跑了156ms的解法](https://codeforces.com/contest/1152/submission/53260183),暂时没看懂…也太强了吧。 +```cpp +#include +using namespace std; +int n, k, m; +void add(int &a, long long b, int M = 1e9 + 7) { a = (a + b) % M; } +int toId(int j, int mask) { return j << m | mask; } +struct Matrix +{ + vector> a; + int n; + Matrix(int n) : n(n), a(n, vector(n)) {} + friend Matrix operator*(const Matrix &a, const Matrix &b) + { + Matrix c(a.n); + for (int i = 0; i < a.n; ++i) + for (int j = 0; j < a.n; ++j) + for (int k = 0; k < a.n; ++k) + add(c.a[i][j], 1LL * a.a[i][k] * b.a[k][j]); + return c; + } + friend Matrix pow(Matrix a, int b) + { + Matrix r(a.n); + for (int i = 0; i < a.n; ++i) + r.a[i][i] = 1; + for (; b; b >>= 1, a = a * a) + if (b & 1) + r = a * r; + return r; + } +}; +int main() +{ + scanf("%d%d%d", &n, &k, &m); + Matrix dp(toId(k + 1, 0)), f(dp); + for (int j = 0; j <= k; ++j) + for (int mask = 0; mask < (1 << m); ++mask) + { + int newMask = (mask << 1) % (1 << m); + f.a[toId(j, newMask)][toId(j, mask)] = 1; + if (j < k) + f.a[toId(j + 1, newMask | 1)][toId(j, mask)] = 1 + __builtin_popcount(mask); + } + dp.a[0][0] = 1, dp = pow(f, n) * dp; + int ans = 0; + for (int mask = 0; mask < (1 << m); ++mask) + add(ans, dp.a[toId(k, mask)][0]); + printf("%d", ans); +} +``` diff --git a/_posts/2019-04-27-The 16th Zhejiang Provincial Collegiate Programming Contest Sponsored by TuSimple.md b/_posts/2019-04-27-The 16th Zhejiang Provincial Collegiate Programming Contest Sponsored by TuSimple.md index 39e2133dd..dfd8965be 100644 --- a/_posts/2019-04-27-The 16th Zhejiang Provincial Collegiate Programming Contest Sponsored by TuSimple.md +++ b/_posts/2019-04-27-The 16th Zhejiang Provincial Collegiate Programming Contest Sponsored by TuSimple.md @@ -4,7 +4,136 @@ categories: - ACM - 题解 --- -# [Element Swapping](http://acm.zju.edu.cn/onlinejudge/showContestProblem.do?problemId=5990) +# [Vertices in the Pocket](https://vjudge.net/problem/ZOJ-4100) +```cpp +#include +using namespace std; +typedef long long ll; +const int N = 1e5 + 9; +int t, n, q, sz[N], f[N]; +int fa(int x) { return x == f[x] ? x : f[x] = fa(f[x]); } +ll c2(ll x) { return x * (x - 1) / 2; } +ll sq(ll x) { return x * x; } +struct Node +{ + ll val[3]; + ll calc() { return (val[1] * val[1] - val[2]) / 2; } +} v[N << 2]; +Node up(const Node &lc, const Node &rc) +{ + Node t; + for (int i = 0; i < 3; ++i) + t.val[i] = lc.val[i] + rc.val[i]; + return t; +} +void build(int l, int r, int x = 1) +{ + for (int i = 0; i < 3; ++i) + v[x].val[i] = 0; + if (l == r) + return; + int mid = l + r >> 1; + build(l, mid, x << 1); + build(mid + 1, r, x << 1 | 1); +} +void update(int p, ll sgn, int l, int r, int x = 1) +{ + if (l == r) + { + v[x].val[0] += sgn; + v[x].val[1] += sgn * l; + v[x].val[2] += sgn * l * l; + return; + } + int mid = l + r >> 1; + if (p <= mid) + update(p, sgn, l, mid, x << 1); + else + update(p, sgn, mid + 1, r, x << 1 | 1); + v[x] = up(v[x << 1], v[x << 1 | 1]); +} +int askLeft; +ll curAns; +int bin(const Node &suf, ll i, ll k) +{ + for (int l = 1, r = n;;) + { + if (l >= r) + return r; + ll mid = l + r >> 1; + if ((sq(mid * i + suf.val[1]) - mid * sq(i) - suf.val[2]) / 2 >= k) + r = mid; + else + l = mid + 1; + } +} +Node ask(ll k, const Node &suf, int l, int r, int x) +{ + if (l == r) + { + int j = bin(suf, l, k); + Node temp = v[x]; + for (int i = 1; i < 3; ++i) + temp.val[i] = temp.val[i] / temp.val[0] * j; + temp.val[0] = j; + askLeft = l; + return up(suf, temp); + } + int mid = l + r >> 1; + Node tot = up(v[x << 1 | 1], suf); + ll rval = tot.calc(); + if (k <= rval) + return ask(k, suf, mid + 1, r, x << 1 | 1); + return ask(k, tot, l, mid, x << 1); +} +int main() +{ + for (scanf("%d", &t); t--;) + { + scanf("%d", &n); + for (int i = 1; i <= n; ++i) + f[i] = i, sz[i] = 1; + build(1, n + 1); + ll maxEdges = 0, curEdges = 0, blocks = n; + for (int i = 1; i <= n; ++i) + update(1, 1, 1, n + 1, 1); + for (scanf("%d", &q); q--;) + { + ll op; + scanf("%lld", &op); + if (op == 1) + { + int x, y; + scanf("%d%d", &x, &y); + ++curEdges; + if (fa(x) != fa(y)) + { + maxEdges += c2(sz[f[x]] + sz[f[y]]) - c2(sz[f[x]]) - c2(sz[f[y]]); + update(sz[f[x]], -1, 1, n + 1); + update(sz[f[y]], -1, 1, n + 1); + update(sz[f[x]] + sz[f[y]], 1, 1, n + 1); + sz[f[y]] += sz[f[x]]; + f[f[x]] = f[y]; + --blocks; + } + } + else + { + scanf("%lld", &op); + ll minAns = blocks - min(op, blocks - 1LL), maxAns = blocks; + ll k = op - (maxEdges - curEdges); + if (k > 0) + { + Node res = ask(k, Node(), 1, n + 1, 1); + maxAns -= res.val[0] - 1; + } + printf("%lld %lld\n", minAns, maxAns); + } + } + } +} +``` +# [Element Swapping](https://vjudge.net/problem/ZOJ-4101) ```cpp #include using namespace std; @@ -24,7 +153,6 @@ int main() x1 += i * b[i], y1 += i * b[i] * b[i]; ++mp[b[i]]; } - //cerr << x1 << ' ' << y1 << "!\n"; if (x == x1) { if (y == y1) @@ -53,7 +181,6 @@ int main() if ((x - x1) % (b[i] - bj) == 0) { ll j = i + (x - x1) / (b[i] - bj); - //cerr << i << ' ' << b[i] << ' ' << j << ' ' << bj << ' ' << b[j] << "?\n"; if (1 <= j && j <= n && bj == b[j]) ++ans; } @@ -62,27 +189,25 @@ int main() } } ``` -# [Array in the Pocket](http://acm.zju.edu.cn/onlinejudge/showContestProblem.do?problemId=5991) +# [Array in the Pocket](https://vjudge.net/problem/ZOJ-4102) ```cpp #include using namespace std; -const int N = 1e6 + 9; -int t, n, a[N], c[N], r[N], ans[N]; int main() { + int t; for (scanf("%d", &t); t--;) { + int n, imp = 0; scanf("%d", &n); - fill(c + 1, c + n + 1, 0); - fill(ans + 1, ans + n + 1, 0); + vector a(n + 1), c(n + 1), r(n + 1), ans(n + 1); + set> re; + set ce; for (int i = 1; i <= n; ++i) scanf("%d", &a[i]), ++c[a[i]]; - set> re; - set se; for (int i = 1; i <= n; ++i) if (c[i]) - se.emplace(i), re.emplace(r[i] = 2 * c[i], i); - int imp = 0; + ce.insert(i), re.emplace(r[i] = 2 * c[i], i); for (int i = 1; !imp && i <= n; ++i) { int p = re.rbegin()->second; @@ -92,9 +217,9 @@ int main() printf("Impossible\n"); break; } - else if (r[p] < n - i + 1 || a[i] == p) + else if (r[p] < n - i + 1 || p == a[i]) { - auto it = se.begin(); + auto it = ce.begin(); if (*it == a[i]) ++it; p = *it; @@ -108,7 +233,7 @@ int main() if (r[p]) re.emplace(r[p], p); if (--c[ans[i] = p] == 0) - se.erase(p); + ce.erase(p); } if (!imp) for (int i = 1; i <= n; ++i) @@ -116,55 +241,97 @@ int main() } } ``` -# [Sequence in the Pocket](http://acm.zju.edu.cn/onlinejudge/showContestProblem.do?problemId=5993) +# [Traveler](https://vjudge.net/problem/ZOJ-4103) +居然剪枝搜一下就过了… ```cpp #include - using namespace std; -const int N=1e5+10; - -int t, n, b[N]; - -struct Node{ - int x; - int id; - bool operator < (const Node& rhs) const { - if (x!=rhs.x) return x>rhs.x; - else return id>rhs.id; +struct Graph +{ + struct Vertex + { + vector to; + int ind, vis; + }; + vector v; + vector ans; + Graph(int n) : v(n) {} + int dfs(int u, int dep) + { + if (v[u].vis = 1, ans.push_back(u), !dep) + return 1; + for (auto to : v[u].to) + if (!v[to].vis) + { + int ok = 1; + ++v[to].ind; + for (auto to : v[u].to) + if (!--v[to].ind && !v[to].vis) + ok = 0; + if (ok && dfs(to, dep - 1)) + return 1; + --v[to].ind; + for (auto to : v[u].to) + ++v[to].ind; + }; + return ans.pop_back(), v[u].vis = 0; } -}a[N]; - -int main() { +}; +int main() +{ + int t, n; + for (scanf("%d", &t); t--;) + { + scanf("%d", &n); + Graph g(n + 1); + for (int i = 1; i <= n; ++i) + for (auto to : {i / 2, i - 1, i * 2, i * 2 + 1}) + if (2 <= to && to <= n) + g.v[i].to.push_back(to), ++g.v[to].ind; + if (!g.dfs(1, n - 1)) + printf("Impossible\n"); + else + for (int i = 0; i < g.ans.size(); ++i) + printf("%d%c", g.ans[i], i < g.ans.size() - 1 ? ' ' : '\n'); + } +} +``` +# [Sequence in the Pocket](https://vjudge.net/problem/ZOJ-4104) +```cpp +#include +using namespace std; +const int N = 1e5 + 9; +int t, n, b[N]; +pair a[N]; +int main() +{ scanf("%d", &t); - for(int i=1; i<=t; i++) { + for (int i = 1; i <= t; ++i) + { scanf("%d", &n); - for(int i=1; i<=n; i++) { - scanf("%d", &a[i].x); - a[i].id=i; - b[i]=a[i].x;//original + for (int i = 1; i <= n; ++i) + { + scanf("%d", &b[i]); + a[i] = {b[i], i}; } - sort(a+1, a+n+1); - int p=n+1; - int ans=0; - for(int i=1; i<=n; i++) { - p--; - //cout<>()); + int ans = 0; + for (int i = 1, p = n + 1; p && i <= n; ++i) + { + for (--p; p && a[i].first != b[p];) + --p; + if (!p) + ans = n - i + 1; } - cout< using namespace std; -char vowel[6] = {'a', 'e', 'i', 'y', 'o', 'u'}, s[127]; +char vowel[7] = "aeiyou", s[127]; int t; int main() { @@ -178,7 +345,7 @@ int main() } } ``` -# [Lucky 7 in the Pocket](http://acm.zju.edu.cn/onlinejudge/showContestProblem.do?problemId=5995) +# [Lucky 7 in the Pocket](https://vjudge.net/problem/ZOJ-4106) ```cpp #include using namespace std; @@ -187,14 +354,13 @@ int main() int t, n; for (scanf("%d", &t); t--;) { - scanf("%d", &n); - while (n % 7 || n % 4 == 0) + for (scanf("%d", &n); n % 7 || n % 4 == 0;) ++n; printf("%d\n", n); } } ``` -# [Singing Everywhere](http://acm.zju.edu.cn/onlinejudge/showContestProblem.do?problemId=5996) +# [Singing Everywhere](https://vjudge.net/problem/ZOJ-4107) ```cpp #include using namespace std; @@ -277,144 +443,193 @@ int main() } } ``` -# [Fibonacci in the Pocket](http://acm.zju.edu.cn/onlinejudge/showContestProblem.do?problemId=5997) +# [Fibonacci in the Pocket](https://vjudge.net/problem/ZOJ-4108) ```cpp #include - using namespace std; -const int N=1e4+10; - -int t; -char a[N], b[N]; - -int solve(char* s) { - int len=strlen(s); - int ret=0; - for(int i=0; i using namespace std; -const int N = 1e6 + 9; - -int v[N*2],nex[N*2],g[N],fa[N],an[N]; -bool p[N]; - -int tot; -void add(int x,int y){v[++tot] = y;nex[tot] = g[x];g[x] = tot;} -int gf(int x) {return (x == fa[x])? x : fa[x] = gf(fa[x]);} - +struct UnionfindSet : vector +{ + UnionfindSet(int n) : vector(n) + { + for (int i = 0; i < n; ++i) + at(i) = i; + } + void merge(int u, int w) + { + if (w = ask(w), u = ask(u), w != u) + at(w) = u; + } + int ask(int u) { return at(u) != u ? at(u) = ask(at(u)) : u; } +}; int main() { - int T;cin >> T; - while (T--) + int t, n, m; + for (scanf("%d", &t); t--;) { - priority_queue,greater> q; - int n,m;scanf("%d%d",&n,&m); - tot = 0; - for(int i=1; i<=n; i++) fa[i] = i,p[i] = 0,g[i] = 0; - for(int i=1; i<=m; i++) + scanf("%d%d", &n, &m); + vector> g(n); + UnionfindSet ufs(n); + for (int i = 0, x, y; i < m; ++i) { - int x,y;scanf("%d%d",&x,&y); - add(x,y);add(y,x); - int fx = gf(x),fy = gf(y); - if (fx != fy) - { - if (fx y) + swap(x, y); + ufs.merge(x, y); } - int l = 1,r = 0; - int ans = 0; - for(int i=1; i<=n; i++) if (i == fa[i]) q.push(i),p[i] = 1,ans++,r++; - while (l<=r) + priority_queue q; + vector vis(n), ans; + for (int i = 0; i < n; ++i) + if (ufs.ask(i) == i) + vis[i] = 1, q.push(-i); + printf("%d\n", q.size()); + while (!q.empty()) { - int x = q.top();q.pop(); - an[l++] = x; - for(int i=g[x]; i; i = nex[i]) - { - if (p[v[i]]) continue; - p[v[i]] = 1;q.push(v[i]); - r++; - } + ans.push_back(-q.top()); + q.pop(); + for (int to : g[ans.back()]) + if (!vis[to]) + vis[to] = 1, q.push(-to); } - printf("%d\n",ans); - for(int i=1; i using namespace std; -const int N = 1e6 + 9; - -int v[N*2],nex[N*2],g[N],fa[N],an[N]; -bool p[N]; - -int tot; -void add(int x,int y){v[++tot] = y;nex[tot] = g[x];g[x] = tot;} -int gf(int x) {return (x == fa[x])? x : fa[x] = gf(fa[x]);} - +const int N = 2e6 + 9; +typedef long long ll; +int t; +char s[N], s2[N]; +int a[N], b[N]; +char str[N * 2]; +int p[N * 2], len1, len2; +void init() +{ + len1 = strlen(s); + str[0] = '('; + str[1] = '#'; + for (int i = 0; i < len1; i++) + { + str[i * 2 + 2] = s[i]; + str[i * 2 + 3] = '#'; + } + len2 = len1 * 2 + 2; + str[len2] = ')'; +} +ll manacher() +{ + int id = 0, mx = 0; + ll ans = 0; + for (int i = 1; i < len2; i++) + { + if (mx > i) + p[i] = min(mx - i, p[2 * id - i]); + else + p[i] = 1; + for (; str[i + p[i]] == str[i - p[i]]; p[i]++) + ; + if (p[i] + i > mx) + { + mx = p[i] + i; + id = i; + } + ans += p[i] / 2; + } + return ans; +} int main() { - int T;cin >> T; - while (T--) + scanf("%d", &t); + for (int i = 1; i <= t; i++) { - priority_queue,greater> q; - int n,m;scanf("%d%d",&n,&m); - tot = 0; - for(int i=1; i<=n; i++) fa[i] = i,p[i] = 0,g[i] = 0; - for(int i=1; i<=m; i++) + scanf("%s", s); + scanf("%s", s2); + int n = strlen(s); + for (int i = 1; i <= n; i++) { - int x,y;scanf("%d%d",&x,&y); - add(x,y);add(y,x); - int fx = gf(x),fy = gf(y); - if (fx != fy) - { - if (fx= 1) + R--; + if (L == n + 1) { - int x = q.top();q.pop(); - an[l++] = x; - for(int i=g[x]; i; i = nex[i]) + init(); + printf("%lld\n", manacher()); + } + else + { + int len = R - L + 1; + int ok = 1; + + for (int i = L; i <= R; i++) + { + if (a[i] != b[R + L - i] || b[i] != a[R + L - i]) + { + ok = 0; + break; + } + } + + if (!ok) + printf("0\n"); + else { - if (p[v[i]]) continue; - p[v[i]] = 1;q.push(v[i]); - r++; + int cnt = 1; + for (int i = 1; i <= min(L - 1, n - R); i++) + { + if (a[L - i] == b[R + i] && b[L - i] == a[R + i]) + { + cnt++; + } + else + break; + } + printf("%d\n", cnt); } } - printf("%d\n",ans); - for(int i=1; i