牛客小白赛-⑨运算(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)y9->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;
}

浙公网安备 33010602011771号