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 @@
-
+
{{ 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