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 }
View Code

 

posted @ 2019-09-27 22:47  zjxxcn  阅读(176)  评论(0编辑  收藏  举报