Codeforces 1373E - Sum of Digits (构造)
Description
题目大意:
\(f(x)\)为十进制下x每一位上的数字的和。求满足\(f(x)+f(x+1)+...+f(x+k)=n\)的最小x。
思路
由于k特别小(<=9),故x+k至多发生一次进位。x每加1,必有某一位加上1。如果发生进位,那么\(f(x)\)只要额外减去若干个9(进位发生后9变为0,要减去)。
但是由于不知道加多少会发生进位,所以可以枚举个位是多少,假设是a。如果(a+k)>10,说明发生了进位。
所以枚举个位a和进位影响的9的个数i。故原式可得
\[(k+1) \cdot f(x)+\frac{k \cdot (k+1)}{2}-9 \cdot t \cdot i=n
\]
可以求出f(x)。(其中t代表有多少个f(x)发生进位,就要减去多少若干个9)
由于不知道9的个数上限,所以我枚举200个,可以AC。
对枚举出来的每个f(x),除了个位,其它低的位要尽可能大,使得高位尽可能小和低,同时要保证进位只能影响到i个9。这个根据f(x)的值贪心构造x就好了。
#include <iostream>
#include <cstdio>
#include <queue>
#include <algorithm>
#include <map>
#include <set>
#include <vector>
#include <cstring>
#include <string>
#include <stack>
#include <deque>
#include <cmath>
#include <iomanip>
#include <cctype>
#define endl '\n'
#define IOS std::ios::sync_with_stdio(0);
#define FILE freopen("..//data_generator//in.txt","r",stdin),freopen("res.txt","w",stdout)
#define FI freopen("..//data_generator//in.txt","r",stdin)
#define FO freopen("res.txt","w",stdout)
#define pb push_back
#define mp make_pair
#define seteps(N) fixed << setprecision(N)
typedef long long ll;
using namespace std;
/*-----------------------------------------------------------------*/
#define INF 0x3f3f3f3f
const int N = 2e2 + 10;
const double eps = 1e-8;
string s;
bool build(int fx, int x, int i) {
s.clear();
s.push_back(x + '0');
fx -= x;
for(int p = 0; p < i - 1; p++) {
s.push_back('9');
fx -= 9;
}
if(fx < 0) return false;
if(i && fx > 8) {
fx -= 8;
s.push_back('8');
}
while(fx > 9) {
fx -= 9;
s.push_back('9');
}
if(fx) s.push_back(fx + '0');
reverse(s.begin(), s.end());
return true;
}
string smin(const string &s1, const string &s2) {
if(!s1.size()) return s2;
if(!s2.size()) return s1;
if(s1.size() == s2.size()) return s1 < s2 ? s1 : s2;
return s1.size() < s2.size() ? s1 : s2;
}
int main() {
IOS;
int t;
cin >> t;
while(t--) {
int n, k;
cin >> n >> k;
int rn = n;
n -= (k + 1) * k / 2;
string ans;
for(int x = 0; x <= 9; x++) { //枚举个位
int t = (x + k) / 10 * ((x + k) % 10 + 1);
for(int i = 1; i <= 200; i++) {
if((n + 9 * i * t) % (k + 1)) continue;
int fx = (n + 9 * i * t) / (k + 1);
if(fx > rn) break;
if(x > fx) break;
if(!t) {if(!build(fx, x, 0)) break;}
else {if(!build(fx, x, i)) break;}
ans = smin(ans, s);
break;
}
}
if(ans.empty()) cout << -1 << endl;
else cout << ans << endl;
}
}