补题连接: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; }