相似颜色
#pragma comment(linker, "/STACK:102400000,102400000") #include<stdio.h> #include<string.h> #include<stdlib.h> #include<vector> #include<algorithm> #include<iostream> #include<map> #include<queue> #include<stack> #include<string> #include<functional> #include<math.h> //#include<bits/stdc++.h> using namespace std; typedef long long lint; typedef vector<int> VI; typedef pair<int, int> PII; typedef queue<int> QI; void makedata() { freopen("input.txt", "w", stdout); fclose(stdout); } int main() { #ifndef ONLINE_JUDGE freopen("input.txt", "r", stdin); #endif //makedata(); std::ios::sync_with_stdio(0), cin.tie(0); char ch[10]; int a[10]; scanf("%s", ch); for (int i = 1; i <= 6; i++) { if ('0' <= ch[i] && ch[i] <= '9') a[i] = ch[i] - '0'; else a[i] = ch[i] - 'a' + 10; } printf("#"); for (int i = 1; i <= 3; i++) { int x = a[i * 2 - 1] * 16 + a[i * 2]; x = (x + 8) / 17; if (x < 10) printf("%d", x); else printf("%c", x - 10 + 'a'); } return 0; }
挑选子集
显然选出来的m个数对k同余。把n个数字按除k的余数分成k组,每组计算组合数相加。
#pragma comment(linker, "/STACK:102400000,102400000") #include<stdio.h> #include<string.h> #include<stdlib.h> #include<vector> #include<algorithm> #include<iostream> #include<map> #include<queue> #include<stack> #include<string> #include<functional> #include<math.h> //#include<bits/stdc++.h> using namespace std; typedef long long lint; typedef vector<int> VI; typedef pair<int, int> PII; typedef queue<int> QI; void makedata() { freopen("input.txt", "w", stdout); fclose(stdout); } class AandC { public: long long *fac, *inv, *f; long long mod; AandC(long long m, int n) { mod = m; fac = (long long *)malloc((n) * sizeof(long long)); inv = (long long *)malloc((n) * sizeof(long long)); f = (long long *)malloc((n) * sizeof(long long)); fac[0] = fac[1] = inv[0] = inv[1] = f[0] = f[1] = 1; for (int i = 2; i < n; i++) { fac[i] = fac[i - 1] * i % mod; f[i] = (mod - mod / i) * f[mod % i] % mod; inv[i] = inv[i - 1] * f[i] % mod; } } //choose b from a long long A(int a, int b) { return fac[a] * inv[a - b] % mod; } long long C(int a, int b) { return fac[a] * inv[b] % mod * inv[a - b] % mod; } }; const lint mod = 1000000009; AandC ac(mod, 1000); int a[1000]; int main() { #ifndef ONLINE_JUDGE freopen("input.txt", "r", stdin); #endif //makedata(); std::ios::sync_with_stdio(0), cin.tie(0); int n, m, k; cin >> n >> m >> k; memset(a, 0, sizeof(a)); for (int i = 0; i < n; i++) { int x; cin >> x; a[x % k]++; } lint ans = 0; for (int i = 0; i < k; i++) { if (a[i] >= m) { ans += ac.C(a[i], m); ans %= mod; } } cout << ans << endl; return 0; }
矩阵迷宫
动态规划,dp[i][j][k][l]表示位置为i,j,朝向为k,当前已经转弯l次的最小代价;k=0表示当前向右,k=1表示当前向下。
#pragma comment(linker, "/STACK:102400000,102400000") #include<stdio.h> #include<string.h> #include<stdlib.h> #include<vector> #include<algorithm> #include<iostream> #include<map> #include<queue> #include<stack> #include<string> #include<functional> #include<math.h> //#include<bits/stdc++.h> using namespace std; typedef long long lint; typedef vector<int> VI; typedef pair<int, int> PII; typedef queue<int> QI; void makedata() { freopen("input.txt", "w", stdout); fclose(stdout); } int dp[105][105][2][20], a[105][105]; int main() { #ifndef ONLINE_JUDGE freopen("input.txt", "r", stdin); #endif //makedata(); std::ios::sync_with_stdio(0), cin.tie(0); int n; cin >> n; for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++) { cin >> a[i][j]; } } memset(dp, 0x3F, sizeof(dp)); dp[0][0][0][0] = dp[0][0][1][0] = a[0][0]; for (int i = 1; i < n; i++) { dp[0][i][0][0] = dp[0][i - 1][0][0] + a[0][i]; dp[0][i][1][1] = dp[0][i][0][0] + 1; dp[i][0][1][0] = dp[i - 1][0][1][0] + a[i][0]; dp[i][0][0][1] = dp[i][0][1][0] + 1; } for (int i = 1; i < n; i++) { for (int j = 1; j < n; j++) { for (int k = 1; k < 20; k++) { if (k > i + 1 || k > j + 1) break; dp[i][j][0][k] = a[i][j] + min(dp[i][j - 1][0][k], dp[i - 1][j][1][k - 1] + (1 << (k - 1))); dp[i][j][1][k] = a[i][j] + min(dp[i][j - 1][0][k - 1] + (1 << (k - 1)), dp[i - 1][j][1][k]); } } } int ans = 0x3FFFFFFF; for (int i = 0; i < 20; i++) { ans = min(ans, dp[n - 1][n - 1][0][i]); ans = min(ans, dp[n - 1][n - 1][1][i]); } cout << ans << endl; return 0; }
第K小先序遍历
长度为n的中序遍历的可能二叉树数量为f(n)=(2n!)/((n+1)!n!),写成递推形式:f(n+1)=f(n)*(4n+2)/(n+2)。可见f(n+1)/f(n)<4,而n最多不超过30,所以刚好不需要高精度。
solve(i,j,k)表示从输出中序遍历为a[i]~a[j]的第k小的先序遍历。
按i~j区间上的元素从小到大的顺序计算分别以该元素为根节点有多少种可能的二叉树,若可能的二叉树数量大于k,则说明第k小的先序遍历是以该元素为根节点的。
#pragma comment(linker, "/STACK:102400000,102400000") #include<stdio.h> #include<string.h> #include<stdlib.h> #include<vector> #include<algorithm> #include<iostream> #include<map> #include<queue> #include<stack> #include<string> #include<functional> #include<math.h> //#include<bits/stdc++.h> using namespace std; typedef long long lint; typedef vector<int> VI; typedef pair<int, int> PII; typedef queue<int> QI; void makedata() { freopen("input.txt", "w", stdout); fclose(stdout); } lint f[50]; int a[50]; bool v[50]; void solve(int l, int r, int k) { if (l > r) return; memset(v, true, sizeof(v)); int x, y; while (1) { x = 100; for (int i = l; i <= r; i++) { if (v[i] && a[i] < x) x = a[i], y = i; } if (f[y - l]*f[r - y] >= k) break; else k -= f[y - l] * f[r - y], v[y] = false; } cout << a[y] << endl; solve(l, y - 1, 1 + ((k - 1) / f[r - y])); solve(y + 1, r, 1 + ((k - 1) % f[r - y])); } int main() { #ifndef ONLINE_JUDGE freopen("input.txt", "r", stdin); #endif //makedata(); std::ios::sync_with_stdio(0), cin.tie(0); memset(f, 0, sizeof(f)); f[0] = f[1] = 1; for (int i = 1; i < 30; i++) { f[i + 1] = f[i] * (4 * i + 2) / (i + 2); } int n, k; cin >> n >> k; for (int i = 1; i <= n; i++) cin >> a[i]; solve(1, n, k); return 0; }