Codeforces 1216E2 枚举位数+二分
两个二分 枚举位数
#include <bits/stdc++.h> #define MOD 1000000007 using namespace std; typedef long long ll; ll ten[15]; ll check1(ll x) { ll ans = 0; ll l, r; for (ll i = 1; i <= 9; i++) { l = ten[i], r = ten[i + 1] - 1; if (r < x) { ans += i * (2 * x - l - r) * (r - l + 1) / 2; } else { ans += i * (x - l) * (x - l + 1) / 2; break; } } return ans; } ll check2(ll x) { ll ans = 0; ll l, r; for (ll i = 1; i <= 9; i++) { l = ten[i], r = ten[i + 1] - 1; if (r <= x) { ans += i * (r - l + 1); } else { ans += i * (x - l + 1); break; } } return ans; } int main () { ten[1] = 1; for (int i = 2; i <= 10; i++) { ten[i] = ten[i - 1] * 10LL; } int Q; scanf("%d", &Q); while (Q--) { ll n; scanf("%lld", &n); ll l = 0, r = 1e9, mid; while (l < r - 1) { mid = (l + r) >> 1; if (check1(mid) < n) { l = mid; } else { r = mid; } } n -= check1(r - 1); if (n == 0) { printf("%d\n", (r - 1) % 10); continue; } l = 0; r = 1e9; while (l < r - 1) { mid = (l + r) >> 1; if (check2(mid) < n) { l = mid; } else { r = mid; } } n -= check2(r - 1); int len = 0; ll xxx = r, xxxx = r; while (xxx > 0) { xxx /= 10LL; len++; } len -= n; if (len < 0) { continue; } while (len--) { xxxx /= 10; } printf("%lld\n", xxxx % 10); } }