招商银行信用卡中心M-Geeker技术竞赛初赛
招商银行信用卡中心M-Geeker技术竞赛初赛2020
考试时间:(北京时间,UTC+08:00)08-03 15:00:00 -- 16:30:00
第一题:编码与倒置
int main()
{
unordered_map<int, string> um{
{0,"0000"},{1,"1000"},{2,"0100"},
{3,"1100"},{4,"0010"},{5,"1010"},
{6,"0110"},{7,"1110"},{8,"0001"},
{9,"1001"}
};
int n;
cin >> n;
while (n--)
{
int a;
cin >> a;
string str = "";
while (a)
{
str += um[a % 10];
a /= 10;
}
while (str.size() < 12)str += um[0];
int idx = 0;
while (idx < str.size() - 1 && str[idx] == '0')idx++;
cout << str.substr(idx) << endl;
}
}
第二题:字典序的最小值
n为字符串长度,k为字典中字符个数
思路简述:输出字符串的末尾按照字典序从高到低写入,前面利用'a'和'b'间隔填充。
例如:
n=11, k=7
输出:
abababcdefg
int main()
{
int n, k;
cin >> n >> k;
if (n < k || (n>1 && k==1))
{
cout << -1<<endl;
return 0;
}
string str(n,'a');
int idx = n - 1;
for (int i = k-1;i>1;i--)
{
str[idx--] += i;
}
for (int i = 1; i <= idx; i += 2)
{
str[i] = 'b';
}
cout << str << endl;
return 0;
}
第三题:分裂的最大乘积和与最小分裂次数
思路简述:如果分裂k次,那么当前有(k+1)个数字,这(k+1)个数字彼此相乘然后求和,就是当前收益。又这(k+1)个数字的和是固定的(为输入s),令这(k+1)个数尽量平均(参考柯西不等式),则得到的和最大。
例如:333分裂四次得到66, 66, 67, 67, 67,当前的收益为这五个数字两两组合的乘积的和(乘法结合律),即44355。
vector<long> breakN(long& val,int N)
{
long sum = 0;
vector<long> par(N,val/N);
sum = par[0] * N;
int i = 0;
while (sum++ < val)
{
par[i++]++;
}
return par;
}
long calProfit(vector<long>& nums)
{
long res = 0;
for (int i = 0; i < nums.size() - 1; i++)
{
for (int j = i + 1; j < nums.size(); j++)
{
res += nums[i] * nums[j];
}
}
return res;
}
int main()
{
long s, m;
cin >> s >> m;
if(s>m)
{
cout<<0<<endl;
return 0;
}
if(s<=1)
{
cout<<-1<<endl;
return 0;
}
long count = 2;
long profit = 0;
while (profit < m && count<=s)
{
profit = 0;
vector<long> par = breakN(s, count++);
profit = calProfit(par);
}
count -= 2;
if (profit >= m)
cout << count << endl;
else
cout << -1 << endl;
return 0;
}