P10253 说唱
赛时做不出来,看了官方题解很喵哇
题目分析
首先,将 \(f(x)\) 变成一个好看的形式,以 \(123\) 为例,\(f(123)=123+12+1=111+22+3\),即所有位上的数乘上若干个连续的 \(1\) 之和。有 \(k\) 位 \(a\) 的数 \(\overline{aa\dots a}\) 是等于 \(\dfrac{10^ka-a}{9}\),记 \(S\) 为 \(x\) 所有位上数字之和,那么有 \(f(x)=\dfrac{10x-S}{9}\),得到等式 \(9y+S=10x\)。
那么对于给定的一个 \(y\),我们可以枚举 \(10x\),先令 \(p=9y\),这个 \(p\) 就是我们枚举的 \(10x\),一直加 \(1\) 直到 \(p\) 为 \(10\) 的倍数(不然 \(x\) 不为整数了),接下来重复执行以下过程:
-
判断是否有 \(S=p-9y\),如果是,那么答案为 \(\dfrac{p}{10}\),直接退出。
-
将 \(p\) 加上 \(10\),维护 \(S\) 和 \(d\)(其中 \(d\) 为 \(p-9y\))。
-
若 \(d>9\times n\),直接结束判 \(-1\),否则执行第一步(原因是 \(S\) 最大为 \(9n\),\(n\) 为 \(y\) 的位数)。
复杂度分析:给一个数进行 \(n\) 次加一操作,第 \(i\) 位进位次数至多为 \(\lceil\frac{n}{10^i}\rceil\),\(\sum\limits_i\lceil\frac{n}{10^i}\rceil\) 是 \(O(n)\) 的。
代码
注释很详细了 qwq。
#include <bits/stdc++.h>
#define fi first
#define se second
#define pb push_back
#define mk make_pair
#define ll long long
#define space putchar(' ')
#define enter putchar('\n')
using namespace std;
typedef pair <int, int> pii;
typedef vector <int> vi;
inline int read() {
int x = 0, f = 1;
char c = getchar();
while (c < '0' || c > '9') f = c == '-' ? -1 : f, c = getchar();
while (c >= '0' && c <= '9') x = (x<<3)+(x<<1)+(c^48), c = getchar();
return x*f;
}
inline void write(int x) {
if (x < 0) x = -x, putchar('-');
if (x > 9) write(x/10);
putchar('0'+x%10);
}
const int N = 5e5+5;
int p[N], y[N];
void solve() {
memset(p, 0, sizeof(p));
memset(y, 0, sizeof(y));
string s; cin >> s;
y[0] = s.size();//第0储存长度
for (int i = 0; s[i]; ++i) y[y[0]-i] = s[i]-'0';//低位对应低位
for (int i = 1; i <= y[0]; ++i) {
p[i] += y[i]*9;
p[i+1] += p[i]/10;
p[i] %= 10;
}//先p=9y
p[0] = y[0]+1;
while (p[0] > 1 && !p[p[0]]) --p[0];
int sum = 0, d = 0;
if (p[1]) {
d = 10-p[1];//d=p-9y
++p[2], ++p[0], p[1] = 0;//变成10的倍数
for (int i = 1; i <= p[0]; ++i) if (p[i] > 9) ++p[i+1], p[i] = 0;
while (p[0] > 1 && !p[p[0]]) --p[0];
}
for (int i = 1; i <= p[0]; ++i) sum += p[i];//sum即为S
while (1) {
if (sum == d) {
if (p[0] >= 2) for (int i = p[0]; i >= 2; --i) write(p[i]);
else write(0);
enter;
return;
}
++p[2], ++p[0]; ++sum;//加10
for (int i = 2; i <= p[0]; ++i) {
if (p[i] <= 9) break;
else ++p[i+1], p[i] = 0, sum -= 9;
}
while (p[0] > 1 && !p[p[0]]) --p[0];
d += 10;
if (d > 9*y[0]) break;
}
write(-1), enter;
}
int main() {
int t = read();
while (t--) solve();
return 0;
}