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;
    }
}
posted @ 2020-06-26 22:27  limil  阅读(525)  评论(0编辑  收藏  举报