A. Div. 7
Give a number and ask how many bits can be modified at least to divide the number by 7.
Note that 7 is less than 10, so there must be a 7 for every 10 numbers, so you only need to modify one bit at most.
#include <iostream> #include <cmath> #define ll long long using namespace std; int main() { int t; cin >> t; while(t--) { int n; cin >> n; if(n % 7 == 0) cout << n << endl; else { int a = n / 10 * 10; for(int i = 0; i < 9; i++) { if((a + i) % 7 == 0) { cout << a + i << endl; break; } } } } return 0; }
B. Minority
For a 01 string, you can select a substring. If the number of 0 is strictly greater than the number of 1, delete 1. If the number of 1 is strictly greater than the number of 0, delete 0. Ask how many can be deleted at most.
First, if the number of 0 and 1 in the whole string is different, select the whole string directly; If it is the same, select the substring composed of all characters except the first character of the string, so it is obvious that the answer is the largest.
#include <iostream> #include <cmath> #define ll long long using namespace std; int main() { int t; cin >> t; while(t--) { string s; cin >> s; int zero = 0, one = 0; for(int i = 0; i < s.size(); i++) { if(s[i] == '0') zero++; else one++; } if(zero == one) cout << zero - 1 << endl; else cout << min(zero, one) << endl; } return 0; }
C. Kill the Monster
The most important thing is to note that the range of k is only 2e5 in total. Naturally, I want to enumerate k and judge whether I can defeat it. The condition of hundreds is that the number of character attacks is less than or equal to the number of monster attacks.
#include <iostream> #include <cmath> #define ll long long using namespace std; ll hc, dc, hm, dm, k, w, a; bool check() { ll num1 = ceil(1.0 * hm / dc); ll num2 = ceil(1.0 * hc / dm); return num1 <= num2; } int main() { int t; cin >> t; while(t--) { cin >> hc >> dc; cin >> hm >> dm; cin >> k >> w >> a; //Note that the sum of k does not exceed 2e5 bool ok = 0; for(ll i = 0; i <= k; i++) {//i plus hc hc += i * a; dc += (k - i) * w; if(check()) { ok = 1; break; } hc -= i * a; dc -= (k - i) * w; } if(ok) puts("YES"); else puts("NO"); } }
D. Make Them Equal
First, note that since each ai starts with 1, the number of times ai reaches bi is fixed. You can preprocess the number of times from 1 to each number in the range of 1 to 1000, and then in fact, this problem becomes the simplest 01 knapsack model. In the case of preprocessing, I first thought of multiplication / enumeration factor greed, but in fact, this is not necessarily the optimal solution. A correct approach is to find the shortest path once. The starting point is 1. The path length from a to b is the number of times from a to b. It should also be noted that the K range 1e6 is displayed in the input description. If 1e6 is directly opened in the second dimension of dp array, it must be TLE/MLE. The range of b is 1000. According to the pure multiplication method, a number can be transformed up to 2log 1000 times. If the enumeration factor is greedy, the transformation times will be reduced. The upper bound of the Transformation Times of each number is 13. Therefore, if several K is greater than n * 13, k = n * 13 can be taken directly.
#include <iostream> #include <vector> #include <queue> #include <cstring> using namespace std; int n, k, dp[13005], a[1005], b[1005], c[1005], num[1005], f[1005], v[1005]; void dijkstra() { memset(v, 0, sizeof(v)); memset(f, 0x3f, sizeof(f)); priority_queue<pair<int, int> > q; f[1] = 0; q.push(make_pair(0, 1)); while(q.size()) { int now = q.top().second; q.pop(); if(v[now]) continue; v[now] = 1; for(int i = 1; i <= now; i++) { int nxt = now + now / i; if(nxt <= 1000 && f[nxt] > f[now] + 1) { f[nxt] = f[now] + 1; q.push(make_pair(-f[nxt], nxt)); } } } } int main() { int t; cin >> t; dijkstra(); while(t--) { cin >> n >> k; for(int i = 0; i <= 13000; i++) dp[i] = 0; for(int i = 1; i <= n; i++) { cin >> b[i]; a[i] = 1; num[i] = 0; } for(int i = 1; i <= n; i++) { cin >> c[i]; } for(int i = 1; i <= n; i++) { num[i] = f[b[i]]; } int ans = 0; for(int i = 1; i <= n; i++) { for(int j = min(k, 13 * n); j - num[i] >= 0; j--) { dp[j] = max(dp[j], dp[j - num[i]] + c[i]); ans = max(ans, dp[j]); } } cout << ans << endl; } return 0; } // 7 12 // 11 57 71 26 31 99 58 // 62 66 82 31 94 18 74