P10253 说唱

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\) 不为整数了),接下来重复执行以下过程:

  1. 判断是否有 \(S=p-9y\),如果是,那么答案为 \(\dfrac{p}{10}\),直接退出。

  2. \(p\) 加上 \(10\),维护 \(S\)\(d\)(其中 \(d\)\(p-9y\))。

  3. \(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;
}
posted @ 2024-03-18 13:08  123wwm  阅读(120)  评论(0)    收藏  举报