補題連接:Hereios
題意:給定 數組大小 \(n\) 和 峯值點 \(k\) 請問是否存在這樣的排序,不存在則輸出-1
數組
先序從 i = 2
開始填,依次 i += 2
,若是這樣還有不夠即 \(k \ne 0\) 則確定不存在這種排序。spa
接下來就是填空位了code
AC 代碼:排序
void solve() { int n, k; cin >> n >> k; vector<int> a(n + 1); int nn = n; for (int i = 2; i <= n; i += 2) { if (k == 0) break; a[i] = nn--, k--; } if (k) { cout << -1 << "\n"; return; } int cur = 1; for (int i = 1; i <= n; ++i) if (!a[i]) a[i] = cur++; for (int i = 1; i <= n; ++i) cout << a[i] << " "; cout << "\n"; }
這道題,還是看了題解都沒怎麼理解是這樣子作的ci
using ll = long long; const ll mod = 1e9 + 7; void solve() { int n; cin >> n; vector<int> a(n); for (int &x : a) cin >> x; int h = 0; for (int i = 0; i < 30; ++i) { h |= 1 << i; for (int x : a) if (not((x >> i) & 1)) h &= ~(1 << i); } int c = count(a.begin(), a.end(), h); ll ans = (ll)c * (c - 1) % mod; for (int i = 1; i <= n - 2; ++i) ans = ans * i % mod; cout << ans << '\n'; }
題意很容易懂:現給一個大數 \(n\) 和 \(m\) 次操做機會,每次操做都要使 \(n\) 的每一個位數 + 1,滿十進一。如:\(1912 \to21023\)字符串
思路:get
因爲 \(m\) 的範圍在 \([1,2e5]\) 就別想着暴力了,嘗試 DP + 預處理string
預處理部分: $DP_{(i,j)}\ $ 表明第 i 次操做時位數值時 j 的變化值it
int M = 2e5 + 10; vector<vector<int>> dp(M + 1, vector<int>(10)); void init() { for (int i = 0; i < 10; ++i) dp[0][i] = 1; for (int i = 1; i <= M; ++i) for (int j = 0; j < 10; ++j) { if (j < 9) dp[i][j] = dp[i - 1][j + 1]; else dp[i][j] = (dp[i - 1][0] + dp[i - 1][1]) % mod; } }
因此根據 DP 數組,能夠快速獲得輸入值 n,m的狀況下最後的位數
void solve() { string s; int m; cin >> s >> m; ll ans = 0; for (char c : s) ans = (ans + dp[m][c - '0']) % mod; cout << ans << "\n"; }
賽後看了下官方題解,發現能夠把二維DP壓縮爲一位DP
\(dp_i\) 定義爲對數字 \(10\) 進行 \(i\) 次運算之後的字符串長度
\(dp_i = 2,∀\ i\) in \([0,8]\)
\(dp_i = 3,\) if \(i = 9\)
即對數字 \(10\) 進行 \(9\) 次運算後最終數字爲 \(109\)
對於其餘狀況:\(dp_i = dp_{i-9} + dp_{i - 10}\)
長度是 \(i - 9\) 次運算和 \(i - 10\) 次運算的和
這裏一樣先預處理
最後的答案爲 \(ans = \sum_{i = 1}^{|s|}((m + (int)(s[i] - '0') < 10)?1:dp_{m-10+(int)(s[i] - '0')})\)
- 時間複雜度爲:\(\mathcal{O}(m+t·|s|)\)
#define int long long const int max_n = 200005, mod = 1000000007; int dp[max_n]; signed main() { for (int i = 0; i < 9; i++) dp[i] = 2; dp[9] = 3; for (int i = 10; i < max_n; i++) { dp[i] = (dp[i - 9] + dp[i - 10]) % mod; } ios_base::sync_with_stdio(false), cin.tie(NULL); int t; cin >> t; while (t--) { int n, m; cin >> n >> m; int ans = 0; while (n > 0) { int x = n % 10; ans += ((m + x < 10) ? 1 : dp[m + x — 10]); ans %= mod; n /= 10; } cout << ans << "\n"; } return 0; }