招商银行信用卡中心2019秋招IT笔试(AI、开发、测试开发方向)第二批

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

X游戏

题目

我们称一个数X 为好数, 如果它的每位数字逐个地被旋转 180 度后,我们仍可以得到一个有效的,且和 X 不同的数。要求每位数字都要被旋转。

如果一个数的每位数字被旋转以后仍然还是一个数字, 则这个数是有效的。0, 1, 和 8 被旋转后仍然是它们自己;25 可以互相旋转成对方;69 同理,除了这些以外其他的数字旋转以后都不再是有效的数字。

现在我们有一个正整数 N, 计算从 1 到 N 中有多少个数 X 是好数?

输入描述:

输入正整数N

输出描述:

输出1到N中好数个数

样例:

10
>--------------------------------------------------<
4

解析

数据不大的时候模拟就行了;

数据很大的时候就要数位DP了,这里就不细说了。

#include <bits/stdc++.h>

int main()
{
    for (int n; std::cin >> n;) {
        int ans = 0;
        for (int i = 1; i < n + 1; ++i) {
            std::string str = [] (int n) -> std::string{
                std::string ret;
                for (; n; ret.push_back(n % 10 + '0'), n /= 10) {}
                return ret;
            }(i);

            std::all_of(std::begin(str), std::end(str), [] (const char c) {
                return c != '3' && c != '4' && c != '7';
            }) &&
            std::any_of(std::begin(str), std::end(str), [] (const char c) {
                return c == '2' || c == '5' || c == '6' || c == '9';
            }) ?
            ++ans : 0;
        }
        std::cout << ans << std::endl;
    }
    return 0;
}

跳格子游戏

题目

假设你正在玩跳格子(所有格子排成一个纵列)游戏。需要 跳完n 个格子你才能抵达终点。
每次你可以跳 12 个格子。你有多少种不同的方法可以到达终点呢?
注意:给定n是一个正整数。

输入描述:

格子数n

输出描述:

跳完n个格子到达终点的方法

样例:

2
>--------------------------------------------------<
2

解析

斐波拉契数列;

数据很大的时候要用矩阵快速幂加速,详情见深入浅出矩阵快速幂及其简单应用

#include <bits/stdc++.h>

int main()
{
    for (int n; std::cin >> n; ) {
        long long f0 = 1, f1 = 1, t;
        for (int i = 2; i <= n; t = f1, f1 += f0, f0 = t, ++i) {}
        std::cout << f1 << std::endl;
    }
    return 0;
}

糖果分配

题目

假设你是一位很有爱的幼儿园老师,想要给幼儿园的小朋友们一些小糖果。但是,每个孩子最多只能给一块糖果。对每个孩子i,都有一个胃口值 gi ,这是能让孩子们满足胃口的糖果的最小尺寸;并且每块糖果j,都有一个尺寸sj。如果 sj >= gi ,我们可以将这个糖果j分配给孩子i,这个孩子会得到满足。你的目标是尽可能满足越多数量的孩子,并输出这个最大数值。

注意:

你可以假设胃口值为正。

一个小朋友最多只能拥有一块糖果。

输入描述:

第一行输入每个孩子的胃口值

第二行输入每个糖果的尺寸

孩子数和糖果数不超过1000

输出描述:

能满足孩子数量的最大值

样例:

1 2 3
1 1
>--------------------------------------------------<
1

解析

贪心,尽量让每个孩子得到刚好合适的糖果。

#include <bits/stdc++.h>

int main()
{
    std::string cindyString, childString;
    std::getline(std::cin, childString);
    std::getline(std::cin, cindyString);
    std::vector<int> cindys, childs;
    auto stringInput = [] (const std::string & str, std::vector<int> & vec) {
        std::stringstream sin(str);
        for (int x; sin >> x; vec.emplace_back(x)) {}
    };
    stringInput(childString, childs);
    stringInput(cindyString, cindys);
    std::sort(std::begin(cindys), std::end(cindys));
    std::sort(std::begin(childs), std::end(childs));
    int ans = 0;
    for (auto it = std::begin(childs), start = std::begin(cindys);
         it != std::end(childs) && start != std::end(cindys); ++it) {
        auto pos = std::lower_bound(start, std::end(cindys), *it);
        if (pos != std::end(cindys)) {
            ++ans;
            start = pos + 1;
        } else
            start = pos;
    }
    std::cout << ans << std::endl;
    return 0;
}

K点游戏

题目

小招喵某日闲来无事,想验一下自己的人品,于是给自己定了一个游戏规则:

这个游戏有三个因素:N,K,W

游戏开始的时候小招喵有0点,之后如果发现自己手上的点不足K点,就随机从1W的整数中抽取一个(包含1W),抽到哪个数字的概率都是相同的。

重复上述过程,直到小招喵获得了K或者大于K点,就停止获取新的点,这时候小招喵手上的点小于等于N的概率是多少?

输入描述:

输入为3个整数,分别对应N,K,W,中间用空格隔开

其中0 <= K <= N <= 100001 <= W <= 10000

输出描述:

输出为概率值,保留5位小数

样例:

21 17 10
>--------------------------------------------------<
0.73278

解析

枚举最后一次取之前已经取了多少点,然后看看还要取多少点能满足>= K并且<= N就行了。

最后一次取了x点的概率可以用记忆化搜索弄出来。

这题比较坑的地方在于保留5位小数,像代码中特殊处理一下才能过这个题。

#include <bits/stdc++.h>

double dfs(int sum, int w, std::vector<double> & dp)
{
    if ((int)dp[sum] + 1)
        return dp[sum];
    double ret = 0;
    for (int i = 1; i <= w && i <= sum; ++i) {
        double s = dfs(sum - i, w, dp) / w;
        ret += s;
    }
    return dp[sum] = ret;
}

int main()
{
    for (int n, k, w; std::cin >> n >> k >> w; ) {
        double ans = 0;
        std::vector<double> dp(k + 1, -1);
        dp[0] = 1;
        for (int pre = 0; pre < k; ++pre) {
            if (k - pre > w) continue;
            ans += dfs(pre, w, dp) * ((std::min(n - pre, w) - (k - pre) + 1.0) / w);
        }
        std::stringstream sout;
        sout << std::setprecision(5) << ans;
        std::cout << sout.str().substr(0, 7) << std::endl;
    }
    return 0;
}

排队唱歌

题目

我们部门要排队唱歌,大家乱哄哄的挤在一起,现在需要按从低到高的顺序拍成一列,但每次只能交换相邻的两位,请问最少要交换多少次

输入描述:

第一行是NN<50000),表示有N个人

然后每一行是人的身高HiHi<2000000,不要怀疑,我们以微米计数),持续N行,表示现在排列的队伍

输出描述:

输出一个数,代表交换次数。

样例:

6
3
1
2
5
6
4
>--------------------------------------------------<
4

解析

这题翻译过来就是,冒泡排序交换的次数,答案是序列的逆序对数。如何求逆序对呢?请参考序列逆序对问题详解

这题的代码就是上面博客的代码。

#include <bits/stdc++.h>

class Solution {
public:
    int InversePairs(std::vector<int> data) {
        std::vector<int> pos(data.size()), arr(data);
        sort(data.begin(), data.end());
        for (int i = 0; i < (int)pos.size(); i++)
            pos[i] = lower_bound(data.begin(), data.end(), arr[i]) - data.begin();

        int c[(const int)data.size() + 1];
        memset(c, 0, sizeof(c));
        long long ret = 0;
        for (int i = 0; i < (int)data.size(); i++)
            add(c, pos[i] + 1, data.size()),
                    ret = (ret + i + 1 - getsum(c, pos[i] + 1));
        return (int)ret;
    }

    int lowbit(int x)
    {
        return x & -x;
    }

    long long getsum(int c[], int i)
    {
        long long ret = 0;
        for (; i > 0; i -= lowbit(i))
            ret = (ret + c[i]);
        return ret;
    }

    void add(int c[], int i, int n)
    {
        for (; i <= n; i += lowbit(i))
            ++c[i];
    }

};

int main()
{
    for (int n; std::cin >> n;) {
        std::vector<int> arr(n);
        for (int i = 0; i < n; std::cin >> arr[i++]) {}
        Solution sol;
        std::cout << sol.InversePairs(arr) << std::endl;
    }
    return 0;
}

猜你喜欢

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