Codeforces Round 802 (Div. 2)
基本情况
A题秒了。
B题经典+4。
C题没想法(大概想了半小时)。
B. Palindromic Numbers
起步
首先很明显是高精。
然后要求加上的数字位数和给的位数相同。
答案不限制,只要回文就行。
第一思路就是口胡几个万能的回文答案。
-
给定的数的第一位比 \(9\) 小
-
显然,把每一位都覆上 \(9\) 可以完成这个情景。
-
for (int i = 0; i < a.len; i++) tb[i] = '9';
-
-
给定的数的第一位就是 \(9\)
-
明显要口胡一个多一位的回文数。
-
然后一开始我就真纯口胡了。
if (a.str()[0] == '9') { int bn = a.len + 1; if (bn & 1) { for (int i = 0; i < bn >> 1; i++) { tb[i] = cnt++; } for (int i = bn >> 1; i < bn; i++) { tb[i] = cnt--; } } else { for (int i = 0; i < bn >> 1; i++) { tb[i] = cnt++; } cnt--; for (int i = bn >> 1; i < bn; i++) { tb[i] = cnt--; } } }
-
大概就是搞一个12321这类的回文串,然而这有可能是错的啊啊
-
改错
幸好是发现了上面那个问题。
比如 \(n = 18\)
那么我口胡的串就是 \(1234567891011...\)
你要不看看自己在说什么。。。
一位放两位了都开始。
所以为啥不找一个和 \(999\) 一样通用的呢
从 \(n = 3\) 来分析:
考虑 \(a\ge 900\) 时,我们发现:
- 只有当 \(a+b-900<1000\)(\(a+b\) 减去最小的 \(a\) 不能超过 \(n\) 位数)
- 且 \(a+b-999\ge100\)(\(a+b\) 减去最大的 \(a\) 不能不到 \(n\) 位数)
- 随便移个项就能得到 \(1099\le a+b<1900\),
- 在这个范围里随便拎个回文数出来(比如 \(1111\))就行了。
代码
大整数类就不复制过来了,太长了。
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
using namespace std;
char tb[100010];
void solve()
{
int n;
memset(tb, '\0', sizeof(tb));
Big_integer a = Big_integer();
cin >> n >> a;
if (a.str()[0] == '9')
for (int i = 0 ; i < a.len + 1; i++) tb[i] = '1';
else
for (int i = 0; i < a.len; i++) tb[i] = '9';
Big_integer b = Big_integer(tb);
cout << b - a << endl;
}
int main()
{
int _; std::cin >> _;
while(_--) solve();
return 0;
}
C. Helping the Nature
要用差分,待我学学。
OK周一学成归来。
思路
我们考虑我们是怎么使得整个序列的数都变成 \(0\):
-
将序列中的所有数都变成同一个数,然后同时加或减某一个数之后才能做到。
-
或者将序列的中间变成 \(0\),将序列的左右部分分别变成同一个数,但是这样跟原问题有啥区别吗,还变得更加复杂了,所以就果断弃掉这个思路。
考虑如何操作使得区间中的所有数都变成同一个数:
我们考虑如果对原序列做差分,那么我们最终的答案就是差分序列所有的值为 \(0\) 时,序列中的所有的数是同一个数。
我们会发现一个很神奇的事情:我们对于一个前缀/后缀整体减一,只会对一个位置的差分值产生影响,加一或减一,那么就利用这个性质一点一点将差分数组变成 \(0\) 就可以了。
注意:这只是将整个序列都变成同一个数,还需要将所有的数都变成 \(0\),这一步不能忘记了。
代码
对于一个差分后的值 \(x\),因为每一次操作都只能加一或减一,所以也就是 \(|x|\) 次操作后能变成 \(0\)。我的代码里维护的 \(h\) 值即差分序列全部变成 \(0\) 之后,原序列中的这个数(即原序列中所有都相同的每个数)是多少。
#include<iostream>
#include<algorithm>
const int N = 2e5 + 10;
int a[N], n;
long long b, ans;
void solve()
{
ans = 0;
std::cin >> n;
for (int i = 1; i <= n; i++)
{
std::cin >> a[i];
}
long long h = a[1];
for (int i = 2; i <= n; i++)
{
b = a[i - 1] - a[i];
ans += abs(b);
if (b > 0) h -= b;
}
ans += abs(h);
std::cout << ans << std::endl;
}
int main()
{
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
std::cout.tie(nullptr);
int _; std::cin >> _;
while(_--) solve();
return 0;
}
然而这是错的!
调了半天发现是 abs
的问题。
我用的 abs
没有声明 std
,所以是 C
自带的,而这个 C
自带的只能处理 int
,long long
就会爆掉。
用C++
的 abs
,即加上 std::abs
就过了。
#include<iostream>
#include<algorithm>
const int N = 2e5 + 10;
int a[N], n;
long long b, ans;
void solve()
{
ans = 0;
std::cin >> n;
for (int i = 1; i <= n; i++)
{
std::cin >> a[i];
}
long long h = a[1];
for (int i = 2; i <= n; i++)
{
b = a[i - 1] - a[i];
ans += std::abs(b);
if (b > 0) h -= b;
}
ans += std::abs(h);
std::cout << ans << std::endl;
}
int main()
{
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
std::cout.tie(nullptr);
int _; std::cin >> _;
while(_--) solve();
return 0;
}