Codeforces Round 1043 (Div. 3) (A ~ C2)
A. Homework
模拟
题意:
给定一个字符串,然后按照要求进行首尾添加,\(V\)放前面\(D\)放后面
思路:
按题意模拟即可
代码:
void solve()
{
int n;
cin >> n;
string a;
cin >> a;
int m;
cin >> m;
string b,c;
cin >> b >> c;
int idx = 0;
for(auto x : c)
{
if(x == 'D') a += b[idx ++];
else a = b[idx ++] + a;
}
cout << a << '\n';
}
B. The Secret Number
数学
题意:
给定一个\(n\)并规定\(n = x + y\),y是在x右面添加若干个0得到的,升序输出符合规定的所有\(x\)
思路:
不难发现\(y = 10 * c * x\),那么\(n = (10 * c + 1) * x\),所以只需枚举\(c\)也就是在x右面添加多少个\(0\),如果这个系数能整除\(n\),此时这个\(x\)就是答案之一,最后排序输出即可
代码:
void solve()
{
int n;
cin >> n;
vector<int> res;
for(int i = 10; ; i *= 10)
{
int t = i + 1;
if(t > n) break;
if(n % t == 0) res.push_back(n / t);
}
sort(res.begin(),res.end());
cout << res.size() << '\n';
for(auto x : res) cout << x << ' ';
if(res.size() != 0) cout << '\n';
}
C1. The Cunning Seller (easy version)
贪心
题意:
你去买西瓜,每次交易可用\(3^{x + 1} + x * 3^{x - 1}\)金币买\(3^x\)个西瓜\((x >= 0)\),在保证最少交易次数前提下求购买n个西瓜所需最少金币
思路:
可以先预处理一下买\(3^i\)个西瓜所需金币数量,然后将\(n\)转换成\(3\)进制,从高位到低位计算一下即可
代码:
void solve()
{
int n;
cin >> n;
vector<int> c(21),pre(21);
pre[0] = 1;
for(int i = 1; i <= 20; i ++) pre[i] = pre[i - 1] * 3;
c[0] = 3;
for(int i = 1; i <= 20; i ++) c[i] = pre[i + 1] + i * pre[i - 1];
int res = 0;
for(int i = 20; i >= 0; i --)
{
if(n >= pre[i])
{
int num = n / pre[i];
n %= pre[i];
res += num * c[i];
}
}
cout << res << '\n';
}
C2. The Cunning Seller (hard version)
贪心
代码写的有点拉了
题意:
与上一题唯一区别是本题要求在保证交易次数不超过\(k\)次购买\(n\)个西瓜所需最少金币数,如果无法在不超过\(k\)次的限制下买\(n\)个西瓜,那么就输出\(-1\)
思路:
首先可以利用上一题计算出购买\(n\)个瓜最小交易次数,如果最小交易次数都大于\(k\)就是无解,那么如何更优的购买呢?
\[\frac{3^{x + 1} + x * 3^{x - 1}} {3^x} = x + \frac{x}{3}
\]
所以不难发现随着\(x\)增大,西瓜单价是递增的,然后还有一个性质就是一个\(i\)等价于\(3\)个\(i - 1\)交易次数较原来增加了\(2\),所以剩下在满足交易次数小于等于k的条件下从高到低要尽可能的将\(n\)所对应的\(3\)进制数位转换到低位,最后计算结果即可
代码:
void solve()
{
int n,k;
cin >> n >> k;
int res = 0;
vector<int> a(22);
for(int i = 20; i >= 0; i --)
{
if(n >= pre[i])
{
int num = n / pre[i];
n %= pre[i];
a[i] = num;
res += num;
}
}
if(res > k)
{
cout << -1 << '\n';
return;
}
for(int i = 20; i > 0; i --)
{
if(!a[i]) continue;
if(res + 2 > k) break;
int cnt = (k - res) / 2;
if(cnt <= 0) break;
if(cnt >= a[i])
{
a[i - 1] += a[i] * 3;
res += a[i] * 2;
a[i] = 0;
}
else
{
a[i - 1] += cnt * 3;
res += cnt * 2;
a[i] -= cnt;
}
}
int cost = 0;
for(int i = 0; i <= 20; i ++)
cost += c[i] * a[i];
cout << cost << '\n';
}