March 27th, 2016
1st question
hihocoder 1283. hiho密码
#include <iostream> #include <vector> using namespace std; int main() { int N; cin >> N; int increment_cnt = 0; vector<int> nums(N); cin >> nums[0]; for (int i = 1; i < N; ++ i) { cin >> nums[i]; increment_cnt = nums[i] > nums[i-1]? increment_cnt + 1: 1; } for (int i = 0; i < N - increment_cnt; ++ i) { cout << nums[i]; if (i != N - increment_cnt - 1) cout << " "; } if (increment_cnt == N) cout << 1 << '\n'; }
2. 2rd question
hihocoder 1284. 机会渺茫
Do remember define N and M as uint64_t instead of int !!!
#include <unordered_set> #include <iostream> #include <cstdint> #include <cmath> using namespace std; uint64_t gcd(uint64_t a, uint64_t b) { if (b == 0) return a; else return gcd(b, a % b); } int main() { uint64_t N, M; cin >> N >> M; unordered_set<uint64_t> ns, ms; uint64_t n = sqrt(N), m = sqrt(M); for (uint64_t i = 1; i <= n; ++ i) if (N % i == 0) { ns.insert(i); if (ns.find(N / i) == ns.end()) ns.insert(N / i); } uint64_t match = 0; for (uint64_t i = 1; i <= m; ++ i) if (M % i == 0) { ms.insert(i); match += (ns.find(i)!=ns.end()? 1: 0); if (ms.find(M / i) == ms.end()) { ms.insert(M / i); match += (ns.find(M/i)!=ns.end()? 1: 0); } } uint64_t divisor = gcd(ns.size() * ms.size(), match); cout << ns.size()*ms.size()/divisor << " " << match/divisor << '\n'; }
3rd question
Hihocoder 1285. 智力竞赛 -- Two dimensional dynamic programming.
rights[i][j]
i: # of stages we have passed
j: j chances we have used
rights[i][j]: the minimal right answers we have to make in j chances, to pass thei# stage
Given ai, s, t, max_chances, we could find out all the solutions(x right answers && y wrong ones) to get the points, which is no less than ai.
1. In every rights[i][j], max_chances = M - j.
2. When j + x + y <= M, we have dynamic equation:
rights[i+1][j+x+y] = min(rights[i+1][j+x+y], rights[i][j] + y);
Source:
#include <vector> #include <map> #include <algorithm> #include <iostream> #include <cmath> #include <cassert> using namespace std; // first: ans_num, second: right ones among answers // sorted by first -- less<int> vector<pair<int, int>> get_solutions(int require, int max_chances, int S, int T) { vector<pair<int, int>> res; for (int wrong = 0; wrong <= max_chances && (wrong-1) * T < require; ++ wrong) { int right = ceil((require - wrong * T) * 1.0 / S); if (wrong + right > max_chances) break; res.emplace_back(make_pair(wrong+right, right)); } return res; } void gao() { // input int N, M, S, T; cin >> N >> M >> S >> T; const int NO = M + 1; vector<int> A; for (int i = 0; i < N; ++ i) { int a; cin >> a; A.push_back(a); } // right[i][j] // i: i# stage ("guan" in Chinese) // j: # of chance has been used // value: # of right answer in j answers vector<vector<int>> rights(N+1, vector<int>(M+1, NO)); // dp init rights[0][0] = 0; for (int i = 0; i <= N-1; ++ i) { int chance_used = NO; for (int j = 0; j <= M; ++ j) if (rights[i][j] != NO) { chance_used = j; break; } if (chance_used == NO) { cout << "No\n"; return; } auto solutions = get_solutions(A[i], M - chance_used, S, T); for (int j = chance_used; j <= M && rights[i][j] != NO; ++ j) for (auto solution: solutions) if (j + solution.first <= M) rights[i+1][j+solution.first] = min(rights[i+1][j+solution.first], rights[i][j] + solution.second); else break; } int min_right = *min_element(rights[N].begin(), rights[N].end()); if (min_right != NO) cout << min_right << '\n'; else cout << "No\n"; } int main() { int Q; cin >> Q; while (Q-- != 0) { gao(); } }