快手算法笔试-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;
}
#快手笔试##快手##笔试题目##春招#
全部评论
 哈哈哈哈哈,我们一样,第三题我也没做出来
1 回复 分享
发布于 2020-03-22 21:32
https://www.nowcoder.com/discuss/388827,我的思路,看上去没什么问题,但是就是WA 0%……大佬能帮忙捉捉虫吗orz
1 回复 分享
发布于 2020-03-22 21:35
0.2是边值情况,采样近似可能不能得分呢,我也是这样做的,例子输出的就不是7.9
1 回复 分享
发布于 2020-03-22 21:54

相关推荐

jack_miller:我给我们导员说我不在这里转正,可能没三方签了。导员说没事学校催的时候帮我想办法应付一下
点赞 评论 收藏
分享
评论
2
4
分享
牛客网
牛客企业服务