快手2019秋季校园招聘算法笔试A卷编程题 - 题解

版权声明:本文为博主原创文章,禁止转载。 https://blog.csdn.net/FlushHip/article/details/83822873

快手算法笔试题,两个动态规划,一个签到题。数据太恶心了,魔法深渊那题,没给模,后来是我自己根据结果猜出来的,模是 1000000003 1000000003 ,居然还不是常规的 1000000007 1000000007 ;善变的同伴那题,应该是卡常数了,而且代码一会过一会不过。。。

题目链接:点这儿

魔法深渊

题目

前几个月放映的头号玩家简直火得不能再火了,作为一个探索终极AI的研究人员,月神自然去看了此神剧。
由于太过兴奋,晚上月神做了一个奇怪的梦,月神梦见自己掉入了一个被施放了魔法的深渊,月神想要爬上此深渊。

已知深渊有N层台阶构成(1 <= N <= 1000),并且每次月神仅可往上爬2的整数次幂个台阶(1、2、4、…),请你编程告诉月神,月神有多少种方法爬出深渊

输入:

输入共有M行,(1 <= M <= 1000)

第一行输入一个数M表示有多少组测试数据,

接着有M行,每一行都输入一个N表示深渊的台阶数

输出:

输出可能的爬出深渊的方式

样例:

4
1
2
3
4

  
  
1 2 3 6

解析

简单动态规划,和上楼梯的斐波拉契数列有点类似,照着那个想一想就明白了。

注意,一定要取模,不然数据范围会炸,虽然题目中没有给出模,但是它的输出数据是取了模的,开头也说了,我试出来的模是 1000000003 1000000003

#include <bits/stdc++.h>

int main()
{
    int p2[10] = {1, 2, 4, 8, 16, 32, 64, 128, 256, 512};
    std::vector<long long> dp(1001, 0);
    dp[0] = 1;
    for (int i = 1; i <= 1000; ++i) {
        for (int j = 0; j < 10 && i >= p2[j]; ++j) {
            dp[i] += dp[i - p2[j]];
            dp[i] %= 1000000003LL;
        }
    }
    int T;
    std::cin >> T;
    for (int n; T--; std::cout << dp[std::cin >> n, n] << std::endl) {}
    return 0;
}

善变的同伴

题目

又到了吃午饭的时间,你和你的同伴刚刚研发出了最新的GSS-483型自动打饭机器人,现在你们正在对机器人进行功能测试。

为了简化问题,我们假设午饭一共有N个菜,对于第i个菜,你和你的同伴对其定义了一个好吃程度(或难吃程度,如果是负数的话……)A[i]

由于一些技(经)术(费)限制,机器人一次只能接受一个指令:两个数L, R——表示机器人将会去打第L~R一共R-L+1个菜。
本着不浪费的原则,你们决定机器人打上来的菜,含着泪也要都吃完,于是你们希望机器人打的菜的好吃程度之和最大
然而,你善变的同伴希望对机器人进行多次测试(实际上可能是为了多吃到好吃的菜),他想知道机器人打M次菜能达到的最大的好吃程度之和

当然,打过一次的菜是不能再打的,而且你也可以对机器人输入-1, -1,表示一个菜也不打

输入:

第一行:N, M
第二行:A[1], A[2], ..., A[N]

输出:

一个数字S,表示M次打菜的最大好吃程度之和

样例:

7 2
1 2 3 -2 3 -10 3
7 4
1 2 3 -2 3 -10 3

  
  
10 12

解析

分析剥离一下,这个题就是最大m段子段和的装饰版。这个也可以自己上网找找资料,理解一下这个动态规划,很基础。

注意:二维动态规划,复杂度 O ( n 2 ) O(n^2) ,空间复杂度要做到 O ( n ) O(n) ,因此用滚动数组优化一下,但是这个题卡常数,交上去的代码时过时不过的。

#include <bits/stdc++.h>
 
#define MAX_SIZE 1000000
 
using LL = long long;
const LL inf = 0x3f3f3f3f;
 
LL a[MAX_SIZE];
LL dp[2][MAX_SIZE];
 
int main()
{
 
    for (LL n, m, pre; EOF != std::scanf("%lld%lld", &n, &m); ) {
        //std::vector<LL> a(n);
        //std::vector< std::vector<LL> > dp(2, std::vector<LL>(n + 1, 0));
        for (int i = 1; i <= n; std::scanf("%lld", &a[i++])) {}
 
        for (int i = 1; i <= m; ++i) {
            pre = dp[i & 1][i - 1] = -inf;
            for (int j = i; j <= n - m + i; ++j) {
                pre = std::max(pre, dp[(i - 1) & 1][j - 1]);
                dp[i & 1][j] = std::max(dp[i & 1][j - 1], pre) + a[j];
            }
        }
 
        LL ans = -inf;
        for (int i = std::min(m, n); i <= n; ans = std::max(ans, dp[std::min(n, m) % 2][i++])) {}
        std::printf("%lld\n", ans);
    }
    return 0;
}

字符串归一化

题目

通过键盘输入一串小写字母(a~z)组成的字符串。
请编写一个字符串归一化程序,统计字符串中相同字符出现的次数,并按字典序输出字符及其出现次数。
例如字符串"babcc“归一化后为”a1b2c2"

输入:

每个测试用例每行为一个字符串,以’\n'结尾,例如cccddecca

输出:

输出压缩后的字符串ac5d2e

样例:

dabcab

  
  
a2b2c1d1

解析

这个,随便怎么做都可以。

#include <bits/stdc++.h>

int main()
{
    for (std::string str; std::cin >> str; std::cout << std::endl) {
        std::map<char, int> mp;
        std:for_each(std::begin(str), std::end(str), [&] (const char c) {
            mp[c]++;
        });
        std::for_each(std::begin(mp), std::end(mp), [] (const std::pair<char, int> & ele) {
            std::cout << ele.first << ele.second;
        });
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/FlushHip/article/details/83822873