A.给你一个小写字母字符串,选择其中k个字母,满足后面的要比前面的至少大2,求最小代价和。
AC代码:
#include <bits/stdc++.h>
using namespace std;
int main()
{
int n, k;
string a;
cin >> n >> k >> a;
sort(a.begin(), a.end());
int sum = 0, pre = 0, ct = 0;
for (int i = 0; i < n; i++)
{
if (a[i] - pre > 1)
{
ct++;
sum += a[i] - 'a' + 1;
pre = a[i];
}
if (ct >= k)
break;
}
cout << (ct >= k ? sum : -1) << endl;
return 0;
}
B.有n个人和m份食物,每个人每天吃一份食物,每份食物都有各自的品种。并且一个人每天吃的食物品种必须一样,问n个人可以坚持多少天。
我用二分写的,其实范围100直接暴力就行了。
AC代码:
#include <bits/stdc++.h>
using namespace std;
int a[110];
int main()
{
int n, m;
cin >> n >> m;
for (int i = 1; i <= m; i++)
{
int temp;
cin >> temp;
a[temp]++;
}
if (m < n)
return cout << 0 << endl, 0;
int l = 1, r = 100, ans;
while (l <= r)
{
int mid = l + r >> 1;
int res = 0;
for (int i = 1; i <= 100; i++)
res += a[i] / mid;
if (res >= n)
{
ans = mid;
l = mid + 1;
}
else
r = mid - 1;
}
cout << ans << endl;
return 0;
}
C.要从1号星球飞到2号星球、2->3、3->4… … n-1->n…n->1。在每个星球上起飞和降落都需要一个代价。问最开始需要携带的燃料至少是多少。
题目看到一半就知道是二分,具体的代价计算规则没看懂,但是看了一下样例解释就知道怎么算了。
据说也可以直接公式On逆推出答案
AC代码:
#include <bits/stdc++.h>
using namespace std;
int a[1010][2];
int main()
{
int n, m;
cin >> n >> m;
for (int i = 1; i <= n; i++)
cin >> a[i][0] >> a[i][1];
double l = 0, r = 100000000000000;
while (r - l >= 0.000001)
{
double mid = (l + r) / 2;
int flag = 1;
double res = m + mid;
res -= res / a[1][0];
if (res < m)
flag = 0;
for (int i = 2; flag && i <= n; i++)
{
res -= res / a[i][0];
res -= res / a[i][1];
if (res < m)
flag = 0;
}
res -= res / a[1][1];
if (res < m)
flag = 0;
if (flag)
{
r = mid - 0.000001;
}
else
l = mid + 0.000001;
}
if (r == 100000000000000)
printf("-1\n");
else
printf("%.8f\n", r);
return 0;
}
D.交互题
一看到题也是二分… 然后看到了But the rocket is broken就知道事情不简单。原来这个机器会给出错误回答,而且错误回答是有循环的。因此我们先求出这个错误循环再求解即可。
AC代码:
#include <bits/stdc++.h>
using namespace std;
int a[100];
int main()
{
int n, m;
cin >> n >> m;
for (int i = 1; i <= m; i++)
{
cout << n << endl;
fflush(stdout);
int temp;
cin >> temp;
if (temp == 0)
return 0;
if (temp == -1)
a[i] = 1;
else
a[i] = -1;
}
int l = 1, r = n, ans, ct = 1;
while (l <= r)
{
int mid = l + r >> 1;
cout << mid << endl;
fflush(stdout);
int temp;
cin >> temp;
temp *= a[ct++];
if (ct > m)
ct = 1;
if (temp == 0)
return 0;
if (temp == -1)
r = mid - 1;
else
l = mid + 1;
}
return 0;
}
E.有m个数字,每种都可以无限使用,问你随意组合之后取模k有多少种结果并列出。
裴蜀定理:对于给定的正整数a,b,方程 a ∗ x + b ∗ y = c a*x+b*y=c a∗x+b∗y=c有解的充要条件为c是gcd(a,b)的整数倍
因此m个数可以表示所有gcd(a1,a2…am)的整数倍的值
AC代码:
#include <bits/stdc++.h>
using namespace std;
int a[100];
int main()
{
int n, k;
cin >> n >> k;
int ans = k;
while (n--)
{
int temp;
cin >> temp;
ans = __gcd(ans, temp % k);
}
cout << k / ans << endl;
for (int i = 0; i < k; i += ans)
cout << i << ' ';
cout << endl;
return 0;
}