POJ 1019
//可能相当计算题了。按递增量为1,2,3,4,5划分,记录下第一个数字串的长度以及开始的位置。
//然后判断出给出的位置属于增量的哪一段,再按等差数列计算它属于哪一个数字串,按在该数字串的位置计算数字,即可。
#include <iostream> #include <cstdio> #include <algorithm> #include <cstring> #include <cmath> using namespace std; struct Position{ int bgn,first; }; Position pos[10]; int su[40001]; int tmp[10]; void initial(){ for(int i=1;i<=9;i++) su[i]=1; for(int i=10;i<=99;i++) su[i]=2; for(int i=100;i<=999;i++) su[i]=3; for(int i=1000;i<=9999;i++) su[i]=4; for(int i=10000;i<=40000;i++) su[i]=5; pos[1].bgn=1; pos[1].first=1; pos[2].bgn=46; pos[2].first=11; pos[3].bgn=9046; pos[3].first=192; pos[4].bgn=1395496; pos[4].first=2893; pos[5].bgn=189414496; pos[5].first=38894; } int work(__int64 p,int k){ p=p-(__int64)pos[k].bgn+1; __int64 bg=(__int64)pos[k].first; double a=k*1.0/2; double b=(bg*1.0-k*1.0/2); // cout<<a<<endl; // cout<<b<<endl; double c=-1.0*p; // cout<<c<<endl; double ans=((sqrt(b*b-4*a*c))-b)/(2*a); // cout<<ans<<endl; __int64 ats=(__int64)ans; // cout<<ats<<endl; __int64 tts=(bg+bg+(__int64)(ats-1)*k)*(__int64)ats/2; if(p==tts) ats--; p=p-(__int64)(bg+bg+(__int64)(ats-1)*(__int64)k)*ats/2; for(int i=1;;i++){ if(p<=(__int64)su[i]){ int t=su[i]; while(i){ tmp[t--]=i%10; i/=10; } return tmp[p]; } p=p-(__int64)su[i]; } } int main(){ initial(); int T,p,ans; scanf("%d",&T); while(T--){ scanf("%d",&p); for(int i=1;i<=5;i++){ if(i<5){ if(p>=pos[i].bgn&&p<pos[i+1].bgn){ ans=work(p,i); break; } } else { ans=work(p,i); } } printf("%d\n",ans); } return 0; }