招商銀行信用卡中心2019秋招IT筆試(AI、開發、測試開發方向)第二批
X遊戲
題目
我們稱一個數X
為好數, 如果它的每位數字逐個地被旋轉 180 度後,我們仍可以得到一個有效的,且和 X
不同的數。要求每位數字都要被旋轉。
如果一個數的每位數字被旋轉以後仍然還是一個數字, 則這個數是有效的。0
, 1
, 和 8
被旋轉後仍然是它們自己;2
和 5
可以互相旋轉成對方;6
和 9
同理,除了這些以外其他的數字旋轉以後都不再是有效的數字。
現在我們有一個正整數 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
個格子你才能抵達終點。
每次你可以跳 1
或 2
個格子。你有多少種不同的方法可以到達終點呢?
注意:給定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
點,就隨機從1
到W
的整數中抽取一個(包含1
和W
),抽到哪個數字的概率都是相同的。
重複上述過程,直到小招喵獲得了K
或者大於K
點,就停止獲取新的點,這時候小招喵手上的點小於等於N
的概率是多少?
輸入描述:
輸入為3個整數,分別對應N,K,W
,中間用空格隔開
其中0 <= K <= N <= 10000
,1 <= 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;
}
排隊唱歌
題目
我們部門要排隊唱歌,大家亂哄哄的擠在一起,現在需要按從低到高的順序拍成一列,但每次只能交換相鄰的兩位,請問最少要交換多少次
輸入描述:
第一行是N
(N<50000
),表示有N
個人
然後每一行是人的身高Hi
(Hi<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;
}