cf 1216e2
https://codeforc.es/problemset/problem/1216/E2
同e1,由于k最大是$10^{18}$,所以我们不能预处理,只能每次二分的时候临时去计算。
1 #include <bits/stdc++.h> 2 using namespace std; 3 #define ll unsigned long long 4 int const N = 20; 5 ll const inf = 1e18; 6 ll dp[N][N], pw[N]; 7 void up(ll &x) 8 { 9 if (x >= inf) 10 x = inf; 11 } 12 void init() 13 { 14 pw[0] = 1; 15 for (int i = 1; i < 19; i++) 16 pw[i] = pw[i - 1] * 10; 17 for (int i = 1; i <= 9; i++) 18 dp[1][i] = dp[1][i - 1] + 1; 19 for (int i = 2; i < 19; i++) 20 for (int j = 1; j < 10; j++) 21 { 22 for (int k = 1; k <= i; k++) 23 { 24 25 ll st = j * pw[i - 1] - (pw[k - 1] - 1); 26 ll ed = (j + 1) * pw[i - 1] - pw[k - 1]; 27 ll num = (ed - st + 1); 28 dp[i][j] += (st + ed) * num / 2; 29 up(dp[i][j]); 30 } 31 } 32 } 33 ll calc(int mid) 34 { 35 int len = 0, a[20]; 36 while (mid) 37 { 38 a[++len] = mid % 10; 39 mid /= 10; 40 } 41 ll res = 0; 42 for (int i = 1; i < len; i++) 43 { 44 for (int j = 1; j < 10; j++) 45 { 46 res += dp[i][j]; 47 if (res >= inf) 48 return inf; 49 } 50 } 51 for (int i = 1; i < a[len]; i++) 52 { 53 res += dp[len][i]; 54 if (res >= inf) 55 return inf; 56 } 57 for (int i = len - 1; i >= 1; i--) 58 { 59 ll tmp = 0, x = a[i] * pw[i - 1]; 60 for (int j = len; j > i; j--) 61 { 62 tmp = tmp * 10 + a[j]; 63 } 64 tmp = tmp * pw[i] - pw[len - 1] + 1; 65 if (a[i] == 0) 66 tmp = 0; 67 tmp = (tmp + tmp + x - 1) * x / 2; 68 res += tmp; 69 if (res >= inf) 70 return inf; 71 for (int j = len - 1; j >= 1; j--) 72 { 73 tmp += (pw[j] - pw[j - 1]) * x; 74 res += tmp; 75 if (res >= inf) 76 return inf; 77 } 78 } 79 return res; 80 } 81 int find(ll t, ll x) 82 { 83 while (1) 84 { 85 x--; 86 if(t==0) while (1); 87 if (x == 0) 88 return t % 10; 89 t /= 10; 90 } 91 } 92 int solve(int r, ll x) 93 { 94 for (int i = 1;; i++) 95 { 96 97 ll tmp = i * (pw[i] - pw[i - 1]); 98 if (tmp < x) 99 x -= tmp; 100 else 101 { 102 int t = pw[i - 1] + (x - 1) / i; 103 int p = (x - 1) % i + 1; 104 return find(t, i - p + 1); 105 } 106 } 107 } 108 int main() 109 { 110 int q, n; 111 init(); 112 scanf("%d", &q); 113 while (q--) 114 { 115 ll x; 116 cin >> x; 117 int l = 1, r = 1e9; 118 while (l < r) 119 { 120 int mid = (l + r) / 2; 121 if (calc(mid + 1) >= x) 122 r = mid; 123 else 124 l = mid + 1; 125 } 126 x -= calc(r); 127 printf("%d\n", solve(r, x)); 128 } 129 return 0; 130 }