记录一下心得
总之这道题的一些细节有点恶心我。
大概思路
依据出现数的位数分层,第一层9个,第二层90,一次类推
差不多是这样子:
1
12
123
…
————
12345678910
1234567891011
…
这样分,然后这对于每一程的位数都是有规律的,成等差数列,我们可以依据每层出现字符个数把该k为出现在哪一层找到,然后k-减去之前层的字符数,现在在找到具体的行,通过等差数列前n项和公式二分找到当前行数,然后减去前i-1行的字符数,在继续在当前行中找第k个字符。。。。依次下去。
代码
#pragma GCC optimize(2)
#include<bits/stdc++.h>
using namespace std;
const int man = 2e5+10;
template<typename T>T gcd(T a, T b) {return b==0?a:gcd(b, a%b);}
template<typename T>T exgcd(T a,T b,T &g,T &x,T &y){if(!b){g = a,x = 1,y = 0;}else {exgcd(b,a%b,g,y,x);y -= x*(a/b);}}
template<typename T>T quick_add(T a,T b,T mod){T ans = 0;while(b){if(b&1)ans = (ans+a)%mod;a = (a+a)%mod;b /= 2;};return ans%mod;}
template<typename T>T quick_mod(T a,T b,T mod){T ans = 1;while(b){if(b&1)ans = ans*a%mod;a = a*a%mod;b /= 2;};return ans%mod;}
#ifndef ONLINE_JUDGE
#define debug(fmt, ...) {printf("debug ");printf(fmt,##__VA_ARGS__);puts("");}
#else
#define debug(fmt, ...)
#endif
typedef unsigned long long ll;
#define int unsigned long long
const ll mod = 1e9+7;
ll ceng[15],sh[15];
inline void init(){
ll shouxian = 0,gongbi = 1,num2 = 9,tp = 0;
for(int i = 1;i <= 11;i++){
shouxian = shouxian + num2/10*(i-1);
sh[i] = shouxian;
ceng[i] = (shouxian + i + shouxian + num2*i)*num2/2;
ceng[i] += tp;
//printf("shouxian:%lld num:%lld ceng:%lld\n",shouxian,num2,ceng[i]);
tp = ceng[i];
num2 *= 10;
}
}
template<typename T>T quick_mod1(T a,T b){T ans = 1;while(b){if(b&1)ans = ans*a;a = a*a;b /= 2;};return ans;}
main() {
#ifndef ONLINE_JUDGE
// freopen("in.txt", "r", stdin);
//freopen("out.txt","w",stdout);
#endif
init();
int q;cin >> q;
while(q--){
ll k;cin >> k;
int id = lower_bound(ceng+1,ceng+12,k)-(ceng+1)+1;
ll shouxian = sh[id];
if(ceng[id-1]==k)id--;
k -= ceng[id-1];
ll l = 1,r = 9*quick_mod1(10ull,id-1);
ll ans = 0;
while(l<=r){
ll mid = l+r>>1;
ll tp = (shouxian + id + shouxian + id*mid)*mid/2;
if(tp<=k){
ans = mid;
l = mid + 1;
}else r = mid - 1;
}
if(k==(shouxian + id + shouxian + id*ans)*ans/2)ans--;
k -= (shouxian + id + shouxian + id*ans)*ans/2;
ll num = 9;ans = 1;
for(int i = 1;;i++){
ll tp = 1ll*i*9*quick_mod1(10ull,1ull*(i-1));
if(k>tp){
k -= tp;
ans = i+1;
}else break;
}
ll tp1 = k/ans;
ll tp2 = k%ans;
ll i = quick_mod1(10ull,ans-1);
char res;
if(!tp2){
i += tp1-1;
char res = (i%10) + '0';
cout << res << endl;
}else {
i += tp1;
tp1 = i;
int j = 0;
char s[20];
while(tp1){
s[j] = (tp1%10)+'0';
tp1 /= 10;
j++;
}
for(int i = 1;i <= tp2;i++){
res = s[--j];
}
cout << res << endl;
}
}
return 0;
}