比賽-訓練賽 (15 Aug, 2018)
阿新 • • 發佈:2018-08-18
next ring right %d 一個 set main scanf sort
1.) 2357數
單調隊列或者搜索都行。
#include <cstdio> #include <deque> using namespace std; typedef long long ll; deque<ll> A[4]; int main() { ll N, x; scanf("%lld", &N); x = 1; while (x < N) { A[0].push_back(x * 2); A[1].push_back(x * 3); A[2].push_back(x * 5); A[3].push_back(x * 7); int p = 0; for (int i = 1; i <= 3; ++i) { if (A[i].front() < A[p].front()) p = i; } x = A[p].front(); for (int i = 0; i <= 3; ++i) { if (A[i].front() == A[p].front()) A[i].pop_front(); } } printf("%lld\n", x); return 0; }
2.) 監獄
區間 DP 。枚舉區間內第一個被釋放的人來轉移狀態。
#include <cstdio> #include <algorithm> #include <cstring> using namespace std; const int INF = 1e9; const int _N = 200; int A[_N], B[15], f[_N][_N], N, M, ans; bool mk[_N]; void test() { int cnt = 0; for (int i = 1; i <= N; ++i) mk[i] = 0; for (int i = 1; i <= M; ++i) { int j; mk[A[B[i]]] = 1; for (j = A[B[i]] - 1; j >= 1 && !mk[j]; --j); cnt += A[B[i]] - 1 - j; for (j = A[B[i]] + 1; j <= N && !mk[j]; ++j); cnt += j - 1 - A[B[i]]; } ans = min(ans, cnt); return; } void fun1() { for (int i = 1; i <= M; ++i) B[i] = i; ans = INF; test(); while (next_permutation(B + 1, B + 1 + M)) test(); printf("%d\n", ans); return; } int dfs(int l, int r) { if (f[l][r] != -1) { return f[l][r]; } if (l == r) { return f[l][r] = 0; } f[l][r] = INF; for (int i = l; i <= r; ++i) { f[l][r] = min(f[l][r], dfs(l, i) + dfs(i + 1, r) + A[r] - A[l - 1] - 2); } // printf("[%d, %d] = %d\n", l, r, f[l][r]); return f[l][r]; } int main() { scanf("%d%d", &N, &M); for (int i = 1; i <= M; ++i) { scanf("%d", &A[i]); } if (N <= 105 && M <= 6) { fun1();//O(M! * N * M) return 0; } sort(A + 1, A + 1 + M); A[0] = 0, A[M + 1] = N + 1; memset(f, -1, sizeof f); printf("%d\n", dfs(1, M + 1)); return 0; }
3.) lucknum
數位 DP 可以拿到 60 分。註意到 DP 方程和組合數的遞推式很像。考慮把 \(n\) 個數位作為球,把這些球扔到 \(m\) 表示 \([0, m-1]\) 這 \(m\) 個數字的桶裏去(或分成 \(m\) 份)。扔完後按桶表示的數字大小從小到大排序,把扔到桶內的球對應的數位上的數,設置為桶表示的數字,就得到了一個合理的 lucknum 。桶內可以為空。隔板法搞一下答案就是 \(\left(_{m-1}^{n+m-1}\right)\) 。
#include <cstdio> #include <algorithm> #include <cstring> using namespace std; typedef long long ll; ll N, M, P; ll mont(ll t1, ll t2) { t1 %= P; ll t = 1; while (t2) { if (t2 & 1) t = t * t1 % P; t2 >>= 1; t1 = t1 * t1 % P; } return t; } int main() { ll dn, up; scanf("%lld%lld%lld", &N, &M, &P); dn = M + N - 1; up = M - 1; if (up > dn - up) up = dn - up; ll t0 = 1, t1 = 1; for (ll i = 1; i <= up; ++i) { t0 = t0 * i % P; t1 = t1 * (dn - i + 1) % P; } printf("%lld\n", t1 * mont(t0, P - 2) % P); return 0; }
比賽-訓練賽 (15 Aug, 2018)