牛客小白赛-⑨运算(Hard Version)

一、题目链接:https://ac.nowcoder.com/acm/contest/125080/E
二、题目大意:这道题的题目大意是给你一个数x,并给你两种操作。第一种操作可以无限次使用,在当前数上进行+9,第二种操作只能使用一次,在当前数上进行9,最终让各个位置上都是9,比如9,99,999。
三、思路:一开始我没有思路方向,于是对样例和自己举了几个例子进行模拟。在没啥清晰的头绪之际大胆总结了一下,一种是直接无限次进行操作1而不进行操作2,一种是在中途某个位置进行一次操作2。
1.x->x+9->x+9+9->x+9+9+9...+9;
2.x->x+9->x+9+...+9->(设此时变为y)y
9->y9+9->y9+...9;
然后对两种方法进行ans取min就好。
第一种情况下,设目标值为G,你能发现你x如果单纯每次加9,你对9的取余的结果是不会变的,于是第一种操作只有在(G-x)%90时才可以进行,其实也就是从G%9x%9推的,当然,你G要大于x。至于怎么找G,其实操作次数比较简单且少,直接枚举即可。然后可以计算出你此时的ans是(G-x)/9。这里如果想不明白的话可以考虑一下27变99。
对于第二种情况,其实表达式也很明了,我最终值依然为一个G,我的核心目的是找中间那个y为多少。看你y能取多少。现在卡住的就是y需不需要考虑尽量取最大或者最小这种可能,又或者随便取。那么你可以计算一下第二种情况的贡献,总共是(y-x)/9+1+(G-9*y)/9,你通分一下可以发现y取最大是最好的,且y的限制值lim小于G/9。至于怎么找y,可以很自然而然地想到二分答案。不过还有一种可行地方法是,我最终找到的那个y,实际上要跟x的取模相同,原因如上一段。所以y在[x,lim]中,最大的y就是lim%9-x%9,发现需要回退多少格,然后加9保证差为正数然后再%9,于是lim-这个回退格数就是我们要找的那个y。
四、总结:这题不难也不是太简单,我认为比较经典且套路,多做多总结就好了(对于我这种若狗来说
五、代码:

点击查看乐哥代码
#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace std;
using namespace __gnu_pbds;
template <typename T>
using ordered_set = tree<T, null_type, less<T>, rb_tree_tag, tree_order_statistics_node_update>;
using ll = long long;
using ldb=long double;
const int MOD = 998244353;
const int INF = 1e9;
// ===================================================
//                  How to Use:
// ===================================================
// ordered_set<int> S;
// S.insert(x);          // 插入
// S.erase(x);           // 删除
// S.find_by_order(k);   // 返回指向第k小元素的迭代器 (0-based)
// S.order_of_key(x);    // 返回小于x的元素个数
// ===================================================
ll qpow(ll a, ll b, ll mod)
{
    ll res = 1;
    a %= mod;
    while (b > 0)
    {
        if (b & 1)
            res = (res * a) % mod;
        a = (a * a) % mod;
        b >>= 1;
    }
    return res;
}

int getlen(ll x)
{
    string s = to_string(x);
    return s.length();
}
struct kind
{
    int len;
    int cnt;
    bool operator<(const kind &other) const
    {
        return len < other.len;
    }
};
ll gcd(ll a, ll b)
{
    return b == 0 ? a : gcd(b, a % b);
}
ll lcm(ll a, ll b)
{
    return a / gcd(a, b) * b;
}
const int MAXN = 2e5 + 5;
vector<int> depth(MAXN);
vector<int> indeg(MAXN, 0);
vector<int> outdeg(MAXN, 0);
// vector<int> g[MAXN];
vector<int> cnt[MAXN];
vector<int> mxdep(MAXN);
vector<int> in(MAXN), out(MAXN);
int tmm = 0;
// void dfs(int u, int d, int fa)
// {
//     depth[u] = d;
//     mxdep[u] = d;
//     in[u] = ++tmm;
//     bool ok = true;
//     for (int i = 0; i < g[u].size(); i++)
//     {
//         int v = g[u][i];
//         if (v == fa)
//             continue;
//         dfs(v, d + 1, u);
//         mxdep[u] = max(mxdep[u], mxdep[v]);
//         ok = false;
//     }
//     out[u] = tmm;
//     if (!ok)
//     {
//         cnt[d].push_back(in[u]);
//     }
// }
struct step
{
    int row;
    int l;
    int r;
};
struct Edge
{
    int u;
    int v;
    ll val;
    bool operator<(const Edge &other) const
    {
        return val < other.val;
    }
};
void solve()
{
    ll x;
    cin >> x;
    vector<long long> a9;
    ll tmp = 0;
    for(int i=0; i<15; i++){
        tmp = tmp * 10 + 9;
        a9.push_back(tmp);
    }
    ll ans = 2e18; 
    for(ll g : a9) {
        if (g >= x && (g - x) % 9 == 0) {
            ans = min(ans, (g - x) / 9);
        }
        ll lim = g / 9;
        if (lim < x) continue; 
        ll cur = x % 9;
        ll yu= lim % 9;
        ll diff = (yu- cur + 9) % 9;
        ll res = lim - diff;
        ll cost = (res - x) / 9 + 1 + (g - res* 9) / 9;
        
        ans = min(ans, cost);
    }
    if(ans == 2e18){
        cout << "-1\n";
    } else {
        cout << ans << "\n";
    }
}
int main()
{
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);
    cout.tie(NULL);
    int t;
    cin >> t;
    while (t--)
        //   {
        solve();
    //}
    return 0;
}
posted @ 2025-12-12 22:23  leeezhusl  阅读(16)  评论(1)    收藏  举报