#define int long long constint P = 998244353, Q = 1 << 20, N = 510; int f[N][N], g[N][N], n; char s[N];
signedmain(){ cin >> (s+1); n = strlen(s+1);
for (int i = 1; i <= n+5; i++) for (int j = 1; j <= n+5; j++) f[i][j] = g[i][j] = 1;
for (int len = 2; len <= n; len++) { for (int l = 1, r; (r = l+len-1) <= n; l++) { f[l][r] = f[l+1][r], g[l][r] = g[l+1][r]; if (s[l] != '(') continue; for (int k = l+1; k <= r; k++) { if (s[k] == ')') { f[l][r] = (f[l][r] + f[l+1][k-1] * f[k+1][r]) % P; g[l][r] = (g[l][r] + g[l+1][k-1] * g[k+1][r]) % Q; } } } }
int res = 0; for (int l = 1; l <= n; l++) for (int r = l; r <= n; r++) res = (res + f[l][r] - g[l][r] + P + (g[l][r] ^ l ^ r)) % P; cout << res << '\n';
return0; }
[NOIP2003] 加分二叉树
设一个 n 个节点的二叉树 tree 的中序遍历为 (1,2,3,⋯,n),其中数字 1,2,3,⋯,n 为节点编号。每个节点都有一个分数(均为正整数),记第 i 个节点的分数为 di,tree 及它的每个子树都有一个加分,任一棵子树 subtree(也包含 tree 本身)的加分计算方法如下:
constint N = 35; int n, f[N][N], a[N]; int g[N][N];
voiddfs(int l, int r){ if (l > r) return; if (!g[l][r]) return; printf("%d ", g[l][r]); dfs(l, g[l][r]-1); dfs(g[l][r]+1, r); }
intmain(){ scanf("%d", &n); for (int i = 1; i <= n; i++) scanf("%d", &a[i]); for (int len = 1; len <= n; len++) { for (int l = 1, r; (r = l+len-1) <= n; l++) { for (int k = l; k <= r; k++) { int now; if (k != l && k != r) now = f[l][k-1]*f[k+1][r] + a[k]; elseif (k == l && k != r) now = f[k+1][r] + a[k]; elseif (k != l && k == r) now = f[l][k-1] + a[k]; else now = a[k]; if (now > f[l][r]) { f[l][r] = now; g[l][r] = k; } } } } printf("%d\n", f[1][n]); dfs(1, n); return0; }
[NOI1999] 棋盘分割
将一个 8×8 的棋盘进行如下分割:将原棋盘割下一块矩形棋盘并使剩下部分也是矩形,再将剩下的部分继续如此分割,这样割了 (n−1) 次后,连同最后剩下的矩形棋盘共有 n 块矩形棋盘。(每次切割都只能沿着棋盘格子的边进行)。
原棋盘上每一格有一个分值,一块矩形棋盘的总分为其所含各格分值之和。
现在需要把棋盘按上述规则分割成 n 块矩形棋盘,并使各矩形棋盘总分的均方差最小。
均方差 σ=[∑i=1n(xi−x)2]/n,平均数 x=(∑i=1nxi)/n,其中 xi 为第 i 块棋盘上的权值之和。
// cmath 里面有个 y1 #define y1 yy1 constint N = 16, M = 9; constdouble INF = 1e20; int s[M][M], n; double f[M][M][M][M][N], avg;
doubleget(int x1, int y1, int x2, int y2){ double sum = s[x2][y2] + s[x1-1][y1-1] - s[x1-1][y2] - s[x2][y1-1] - avg; return sum*sum; }
doubledp(int x1, int y1, int x2, int y2, int k){ double& v = f[x1][y1][x2][y2][k]; if (v >= 0) return v; if (k == 1) return v = get(x1, y1, x2, y2); // 横切 v = INF; for (int i = x1; i <= x2-1; i++) { v = min(v, dp(x1, y1, i, y2, k-1) + get(i+1, y1, x2, y2)); v = min(v, dp(i+1, y1, x2, y2, k-1) + get(x1, y1, i, y2)); }
// 纵切 for (int i = y1; i <= y2-1; i++) { v = min(v, dp(x1, y1, x2, i, k-1) + get(x1, i+1, x2, y2)); v = min(v, dp(x1, i+1, x2, y2, k-1) + get(x1, y1, x2, i)); } return v; }
intmain(){ scanf("%d", &n); for (int i = 1; i <= 8; i++) for (int j = 1; j <= 8; j++) for (int k = 1; k <= 8; k++) for (int p = 1; p <= 8; p++) for (int q = 1; q <= n; q++) f[i][j][k][p][q] = -1;
for (int i = 1; i <= 8; i++) for (int j = 1; j <= 8; j++) { scanf("%d", &s[i][j]); s[i][j] += s[i-1][j] + s[i][j-1] - s[i-1][j-1]; }
typedef __int128 LL; constint N = 90; int n, m, a[N]; LL f[N][N], pow2[N];
voidwrite(LL t){ if (t < 0) putchar('-'), t = -t; if (t < 9) returnputchar('0' + t), void(); write(t / 10); putchar('0' + t % 10); }
LL qmi(LL a, LL k){ LL res = 1; while (k) { if (k & 1) res *= a; a *= a; k >>= 1; } return res; }
LL solveline(){ for (int i = 1; i <= m; i++) scanf("%d", &a[i]); for (int len = 1; len <= m; len++) { for (int l = 1, r; (r = l+len-1) <= m; l++) { if (len == 1) f[l][r] = (LL)pow2[m-len+1] * a[l]; else f[l][r] = max(f[l+1][r] + (LL)a[l] * pow2[m-len+1], f[l][r-1] + (LL)a[r] * pow2[m-len+1]); } } return f[1][m]; }
intmain(){ scanf("%d%d", &n, &m); // 打个表先 for (int i = 1; i <= m; i++) pow2[i] = qmi(2, i); LL res = 0; for (int i = 1; i <= n; i++) res += solveline(); write(res); return0; }
[CSP-S2021] 括号序列
定义“超级括号序列”是由字符 (、)、* 组成的字符串,并且对于某个给定的常数 k
()、(S) 均是符合规范的超级括号序列,其中 S 表示任意一个仅由不超过k个字符 * 组成的非空字符串(以下两条规则中的 S 均为此含义);
如果字符串 A 和 B 均为符合规范的超级括号序列,那么字符串 AB、ASB 均为符合规范的超级括号序列,其中 AB 表示把字符串 A 和字符串 B 拼接在一起形成的字符串;
如果字符串 A 为符合规范的超级括号序列,那么字符串 (A)、(SA)、(AS) 均为符合规范的超级括号序列。
#define int long long #define eb emplace_back constint N = 1010; int T, n, id[N], x[N], y[N], f[N][N]; vector<int> nums, points[N];
intS(int a, int b, int c){ int dx1 = x[a] - x[b], dy1 = y[a] - y[b]; int dx2 = x[a] - x[c], dy2 = y[a] - y[c]; returnabs(dx1 * dy2 - dx2 * dy1); }
intgetr(int R, int p){ int l = 0, r = points[id[p]].size() - 1; while (l < r) { int mid = (l+r+1) >> 1; if (points[id[p]][mid] <= R) l = mid; else r = mid - 1; } return points[id[p]][r]; }
intgetl(int L, int p){ int l = 0, r = points[id[p]].size() - 1; while (l < r) { int mid = (l+r) >> 1; if (points[id[p]][mid] >= L) r = mid; else l = mid + 1; } return points[id[p]][r]; }
signedmain(){ ios::sync_with_stdio(false); cin.tie(0), cout.tie(0); cin >> T; while (T--) { nums.clear(); cin >> n; for (int i = 1; i <= n; i++) { cin >> id[i]; nums.eb(id[i]); points[i].clear(); } sort(nums.begin(), nums.end()); nums.erase(unique(nums.begin(), nums.end()), nums.end()); for (int i = 1; i <= n; i++) { id[i] = lower_bound(nums.begin(), nums.end(), id[i]) - nums.begin() + 1; points[id[i]].eb(i); }
for (int i = 1; i <= n; i++) { cin >> x[i] >> y[i]; x[i+n] = x[i], y[i+n] = y[i], id[i+n] = id[i]; points[id[i]].eb(i+n); }
int ans = 0; for (int len = 3; len <= n; len++) { for (int l = 1, r; (r = l + len - 1) <= 2*n; l++) { if ((id[l] != id[r])) continue;