2016 ACM/ICPC亚洲区沈阳站
Posted mrzdtz220
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了2016 ACM/ICPC亚洲区沈阳站相关的知识,希望对你有一定的参考价值。
签到。
签到
$$f[i] = f[i - 1] + 2 * f[i - 2] + i ^ 4$$
$$
left[
egin{matrix}
1 & 2 & 1 & 0 & 0 & 0 & 0 \
1 & 0 & 0 & 0 & 0 & 0 & 0\
0 &0 & 1 & 4 & 6 &4 & 1 \
0 & 0 & 0 & 1 & 3 & 3 & 1 \
0 & 0 & 0 & 0 & 1 & 2 & 1 \
0 & 0 & 0 & 0 & 0 & 1 & 1 \
0 & 0 & 0 & 0 & 0 & 0 & 1
end{matrix}
ight]
imes
left[
egin{matrix}
f_{i-1} & 0 & 0 & 0 & 0 & 0 & 0 \
f_{i-2} & 0 & 0 & 0 & 0 & 0 & 0\
i^4 &0 & 0 & 0& 0 &0 & 0 \
i^3 & 0 & 0 & 0 & 0 & 0 & 0 \
i^2 & 0 & 0 & 0 & 0 & 0 & 0\
i & 0 & 0 & 0 & 0 & 0 & 0 \
1 & 0 & 0 & 0 & 0 & 0 & 0
end{matrix}
ight]=
left[
egin{matrix}
f_{i} & 0 & 0 & 0 & 0 & 0 & 0 \
f_{i} & 0 & 0 & 0 & 0 & 0 & 0\
(i+1)^4 &0 & 0 & 0& 0 &0 & 0 \
(i+1)^3 & 0 & 0 & 0 & 0 & 0 & 0 \
(i+1)^2 & 0 & 0 & 0 & 0 & 0 & 0\
i+1 & 0 & 0 & 0 & 0 & 0 & 0 \
1 & 0 & 0 & 0 & 0 & 0 & 0
end{matrix}
ight]
$$
#include <bits/stdc++.h> #define ll long long const ll MOD = 2147493647; const int N = 7; struct Mat { ll a[10][10]; Mat() { memset(a, 0, sizeof(a)); } Mat(int x) { memset(a, 0, sizeof(a)); for (int i = 1; i <= N; i++) a[i][i] = 1; } Mat operator * (const Mat &rhs) const { Mat c; for (int i = 1; i <= N; i++) for (int j = 1; j <= N; j++) for (int k = 1; k <= N; k++) c.a[i][j] = (c.a[i][j] + a[i][k] * rhs.a[k][j] % MOD) % MOD; return c; } }; Mat qp(Mat a, int b) { Mat c(1); while (b) { if (b & 1) c = a * c; a = a * a; b >>= 1; } return c; } int main() { int T; scanf("%d", &T); Mat base; base.a[1][1] = 1; base.a[1][2] = 2; base.a[1][3] = 1; base.a[2][1] = 1; base.a[3][3] = 1; base.a[3][4] = 4; base.a[3][5] = 6; base.a[3][6] = 4; base.a[3][7] = 1; base.a[4][4] = 1; base.a[4][5] = 3; base.a[4][6] = 3; base.a[4][7] = 1; base.a[5][5] = 1; base.a[5][6] = 2; base.a[5][7] = 1; base.a[6][6] = 1; base.a[6][7] = 1; base.a[7][7] = 1; while (T--) { int n, a, b; scanf("%d%d%d", &n, &a, &b); if (n == 1) { printf("%d ", a); continue; } if (n == 2) { printf("%d ", b); continue; } n--; n--; Mat ans; ans.a[1][1] = b; ans.a[2][1] = a; ans.a[3][1] = 81; ans.a[4][1] = 27; ans.a[5][1] = 9; ans.a[6][1] = 3; ans.a[7][1] = 1; ans = qp(base, n) * ans; printf("%lld ", ans.a[1][1] % MOD); } return 0; }
经过暑假牛客多校的洗礼,看到团就想到暴搜...
首先用了bfs+bitset。T了。
改成vector判,又T了。
看了一份题解是dfs,存团的是数组。
我把那份代码的数组改成vector,还是T。
这么卡STL的吗...
#include <bits/stdc++.h> const int N = 107; std::vector<int> G[N]; bool mp[N][N]; int ans, n, m, s; void solve(int *a, int u) { if (a[0] == s) { ans++; return; } for (int v: G[u]) { if (v <= u) continue; bool flag = 1; for (int j = 1; j <= a[0]; j++) { if (!mp[a[j]][v]) { flag = 0; break; } } if (!flag) continue; a[++a[0]] = v; solve(a, v); --a[0]; } } int a[N]; int main() { int T; scanf("%d", &T); while (T--) { scanf("%d%d%d", &n, &m, &s); for (int i = 0; i <= n; i++) { G[i].clear(); for (int j = 0; j <= n; j++) mp[i][j] = 0; a[i] = 0; } for (int i = 0; i < m; i++) { int u, v; scanf("%d%d", &u, &v); if (u > v) std::swap(u, v); G[u].push_back(v); mp[u][v] = mp[v][u] = 1; } ans = 0; for (int i = 1; i <= n; i++) { a[0] = 1; a[1] = i; solve(a, i); } printf("%d ", ans); } return 0; }
先把AC自动机建出来。在AC自动机上DP。
$dp[i] = sum frac{1}{6} imes dp[from]$
$from$ 为能转到 $i$ 且不为某个串的结尾的结点
因为会存在环,所以高斯消元就行了。
#include <bits/stdc++.h> const int N = 100 + 7; double mat[N][N]; const double eps = 1e-8; inline void gauss(int n) { for(int i = 0; i <= n; i++) { int r = i; for(int j = i + 1; j <= n; j++) if(std::fabs(mat[r][i]) < std::fabs(mat[j][i])) r = j; if(r != i) std::swap(mat[i], mat[r]); for(int j = 0; j <= n; j++) { if(j == i) continue; double t = mat[j][i] / mat[i][i]; for(int k = i; k <= n + 1; k++) mat[j][k] -= mat[i][k] * t; } } for(int i = 1; i <= n; i++) { mat[i][n + 1] /= mat[i][i]; } } struct Aho { static const int sz = 6; int ch[N][sz], last[N], fail[N], tol; bool end[N]; void init() { tol = 0; newnode(); } inline int newnode() { memset(ch[tol], 0, sizeof(ch[tol])); last[tol] = fail[tol] = end[tol] = 0; return tol++; } void insert(int *a, int n) { int u = 0; for (int i = 0; i < n; i++) { int id = a[i] - 1; if (!ch[u][id]) ch[u][id] = newnode(); u = ch[u][id]; } end[u] = 1; } void build() { std::queue<int> que; for (int i = 0; i < sz; i++) if (ch[0][i]) que.push(ch[0][i]), fail[ch[0][i]] = last[ch[0][i]] = 0; while (!que.empty()) { int u = que.front(); que.pop(); end[u] |= end[last[u]]; for (int i = 0; i < sz; i++) { int &v = ch[u][i]; if (v) { fail[v] = ch[fail[u]][i]; que.push(v); last[v] = end[fail[v]] ? fail[v] : last[fail[v]]; } else { v = ch[fail[u]][i]; } } } } void solve() { memset(mat, 0, sizeof(mat)); mat[0][tol] = -1.0; for (int i = 0; i < tol; i++) { mat[i][i] = -1.0; if (end[i]) continue; for (int j = 0; j < sz; j++) mat[ch[i][j]][i] += 1.0 / 6; } gauss(tol - 1); bool flag = 0; for (int i = 0; i < tol; i++) if (end[i]) { if (flag) putchar(‘ ‘); printf("%.6f", mat[i][tol]); flag = 1; } puts(""); } } ac; int a[20]; int main() { int T; scanf("%d", &T); for (; T--; ) { int n, l; scanf("%d%d", &n, &l); ac.init(); for (int i = 1; i <= n; i++) { for (int j = 0; j < l; j++) scanf("%d", a + j); ac.insert(a, l); } ac.build(); ac.solve(); } return 0; }
$dp[u] = min(dp[anc] + (sum[u] - sum[anc])^2 + p)$
$anc$ 为 $u$ 到根的路径上的结点。
斜率优化DP一下。在进入一个结点时存储一下对当前队列的修改,离开一个结点时改回去,这样就能保证进入一个结点时,队列存储的都是它的祖先。
#include <bits/stdc++.h> #define pii pair<int, int> #define ll long long #define fi first #define se second const int N = 1e5 + 7; const double eps = 1e-10; ll dp[N]; int n, p, que[N], l, r; ll sum[N]; std::vector<std::pii> G[N]; inline ll sqr(ll x) { return x * x; } inline ll up(int i, int j) { return dp[i] + sqr(sum[i]) - dp[j] - sqr(sum[j]); } inline ll down(int i, int j) { return sum[i] - sum[j]; } ll ans; void dfs(int u, int fa = 0) { std::vector<std::pii> vec; int x = l, y = r; while (l < r && up(que[l + 1], que[l]) <= down(que[l + 1], que[l]) * 2 * sum[u]) { vec.push_back(std::pii(l, que[l])); l++; } if (u != 1) { dp[u] = dp[que[l]] + sqr(sum[u] - sum[que[l]]) + p; ans = std::max(ans, dp[u]); } while (l < r && up(que[r], que[r - 1]) * down(u, que[r]) >= up(u, que[r]) * down(que[r], que[r - 1])) { vec.push_back(std::pii(r, que[r])); r--; } que[++r] = u; for (auto v: G[u]) { if (v.fi == fa) continue; sum[v.fi] = sum[u] + v.se; dfs(v.fi, u); } l = x, r = y; for (auto p: vec) que[p.fi] = p.se; } int main() { int T; scanf("%d", &T); while (T--) { scanf("%d%d", &n, &p); for (int i = 1; i <= n; i++) dp[i] = sum[i] = 0, G[i].clear(); for (int i = 1, u, v, w; i < n; i++) { scanf("%d%d%d", &u, &v, &w); G[u].push_back(std::pii(v, w)); G[v].push_back(std::pii(u, w)); } dp[1] = -p; que[l = r = 1] = 0; ans = 0; dfs(1); printf("%lld ", ans); } return 0; }
以上是关于2016 ACM/ICPC亚洲区沈阳站的主要内容,如果未能解决你的问题,请参考以下文章
HDU 5950 Recursive sequence 递推+矩阵快速幂 (2016ACM/ICPC亚洲区沈阳站)
HDU 5950 - Recursive sequence - [矩阵快速幂加速递推][2016ACM/ICPC亚洲区沈阳站 Problem C]