快手算法笔试-A卷(只通过2.2, 太难了吧....)
请会做3、4题的大佬多指教~
1. 将n分成K个正整数,使得这K个正整数之和是n,并且乘积最大,求最大乘积。
dp[i][j]表示i分成j个正整数的最大乘积,时间复杂度:。
#include #define IOS ios_base::sync_with_stdio(0); cin.tie(0); using namespace std; typedef long long ll; #define mp make_pair #define fi first #define se second #define pb push_back #define PI pair const double pi = acos(-1.0); const int inf = 0x3f3f3f3f; const ll INF = 0x3f3f3f3f3f3f3f3fll; const ll mod = (ll)(1e9 + 7); const int N = 1010; ll dp[N][15]; int main() { int K, n; cin >> K >> n; dp[0][0] = 1; for (int i = 1; i <= n; ++i) { for (int k = 1; k <= K; ++k) { for (int j = 1; j <= i; ++j) { dp[i][k] = max(dp[i][k], dp[i-j][k-1] * j); } } } cout << dp[n][K] << endl; return 0; }
2. 二维矩阵从左上角到右下角,求最短路径和。只能向下或者向右。
扫一遍即可。dp[i][j] = min(dp[i-1][j], dp[i][j-1]) + A[i][j]。
3. 定义一种生成随机序列的方式:给定S, A, B, P, 初始arr[0] = S, 接下来arr[i+1] = (arr[i] * A + B) % P, 并且arr数组里的每个数字最多出现两次,当某个数字出现3次时,终止序列生成。给定两组S, A, B, P分别生成两个序列,求两个序列的最长公共子序列.。
不会。
UPD:在@六月雪Yuni 大佬的提醒下,第三题大概会了啊。。。。就是把LCS问题转化成LIS问题。。
#include <bits/stdc++.h> #define IOS ios_base::sync_with_stdio(0); cin.tie(0); using namespace std; typedef long long ll; #define mp make_pair #define fi first #define se second #define pb push_back #define PI pair<int,int> const double pi = acos(-1.0); const int inf = 0x3f3f3f3f; const ll INF = 0x3f3f3f3f3f3f3f3fll; const ll mod = (ll)(1e9 + 7); const int N = 1000010; int T, S[2], A[2], B[2], P[2]; vector<int> data[2]; vector<int> gen(int s, int a, int b, int p) { vector<int> ret({s}); unordered_map<int, int> cnt; cnt[s] = 1; while (1) { int x = (1LL * ret[ret.size()-1] * a % p + b) % p; if (cnt.find(x) == cnt.end()) cnt[x] = 0; cnt[x] += 1; if (cnt[x] >= 3) { break; } ret.emplace_back(x); } return ret; } int LIS(vector<int> A) { int n = A.size(); if (n <= 1) return 1; int data[n], m = 1; data[0] = A[0]; for (int i = 1; i < n; ++i) { int pos = lower_bound(data, data + m, A[i]) - data; data[pos] = A[i]; if (pos == m) m++; } return m; } int main() { cin >> T; while (T--) { for (int i = 0; i < 2; ++i) cin >> S[i] >> A[i] >> B[i] >> P[i]; for (int i = 0; i < 2; ++i) data[i] = gen(S[i], A[i], B[i], P[i]); for (auto x: data[0]) cout << x << " "; cout << endl; for (auto x: data[1]) cout << x << " "; cout << endl; // 记录第一个序列中每个数字的位置 unordered_map<int, pair<int, int> > pos; for (int i = 0; i < data[0].size(); ++i) { int x = data[0][i]; if (pos.find(x) == pos.end()) { pos[x] = mp(i, -1); } else { pos[x] = mp(pos[x].fi, i); } } // 得到转换后的第二个序列 vector<int> filter; for (int i = 0; i < data[1].size(); ++i) { int x = data[1][i]; if (pos.find(x) == pos.end()) continue; if (pos[x].fi != -1) { filter.emplace_back(pos[x].fi); pos[x].fi = -1; } else { filter.emplace_back(pos[x].se); } } cout << LIS(filter) << endl; } return 0; }
4. 给定一个椭球:(x-a)^2/d^2 + (y-b)^2/e^2 + (z-c)^2/f^2 = 1,求中心在原点的单位球的表面,在椭球内部和在椭球外部的表面积分别是多少。
球表面积公式是。采样去近似,只拿了20%的分。。。
#include <bits/stdc++.h> using namespace std; const double pi = acos(-1.0); double a, b, c, d, e, f; bool check(double x, double y, double z) { double s = (x-a) * (x-a) / d + (y-b)*(y-b)/e + (z-c)*(z-c)/f; return s <= 1; } int main() { cin >> a >> b >> c >> d >> e >> f; d *= d, e*=e, f*=f; double step1 = 0.0005, step2 = 0.0005; double total = 0, inner = 0; for (double i = -1; i <= 1; i += step1) { double left = sqrt(1 - i * i); for (double j = -left; j <= left; j += step2) { double z = sqrt(1 - i*i - j*j); if (z != 0) total += 2, inner += check(i, j, z) + check(i, j, -z); else total += 1, inner += check(i, j, z); } } double A1 = inner / total * 4 * pi, A2 = 4 * pi - A1; cout << A1 << " " << A2 << endl; return 0; }#快手笔试##快手##笔试题目##春招#