设begin[k]为Sk的第一个元素,根据题意首先可以对begin[k]打表,k最大为31628,然后二分查找。
额,感觉可以推下公式。
当1<=k<=9时,begin[k] = begin[1]+k*(k-1)/2。
当10<=k<=99时,begin[k] = begin[10]+k*(k-10)。
当100<=k<=999时,begin[k] = begin[100]+(3k+81)(k-100)/2。
当1000<=k<=9999时,beigin[k] = begin[1000]+(k-1000)(2k+891)。
当10000<=k<=99999时,begin[k] = begin[10000]+(5k+27783)(k-10^4)/2。
根据上述公式,可以由输入pos推出pos处在哪个Sk,因为定点的问题,解方程时对结果加0.5再向0方向取整,可以保证求出结果只会是k或者k+1,再判定一下即可。
#include<cstdio>
#include<cmath>
#define k_pos1(k) ((k)*((k)-1)/2)
#define k_pos2(k) ((k)*((k)-10))
#define k_pos3(k) ((3*(k)+81)*((k)-100)/2)
#define k_pos4(k) ((2*(k)+891)*((k)-1000))
#define k_pos5(k) ((5*(k)+27783)*((k)-10000)/2)
int judge(long long k,int pos,int n) //将k转换成64位,防止乘法溢出
{
switch(n)
{
case 1: if(pos >= k_pos1(k))
return pos-k_pos1(k)+1;
else
return pos-k_pos1(k-1)+1;
case 2: if(pos >= k_pos2(k))
return pos-k_pos2(k)+1;
else
return pos-k_pos2(k-1)+1;
case 3: if(pos >= k_pos3(k))
return pos-k_pos3(k)+1;
else
return pos-k_pos3(k-1)+1;
case 4: if(pos >= k_pos4(k))
return pos-k_pos4(k)+1;
else
return pos-k_pos4(k-1)+1;
case 5: if(pos >= k_pos5(k))
return pos-k_pos5(k)+1;
else
return pos-k_pos5(k-1)+1;
}
}
int calc_pos(int pos,int n)
{
switch(n)
{
case 1: return judge(floor(sqrt(2.0*pos+0.25)+0.5+0.5),pos,n);
case 2: return judge(floor(sqrt(pos*1.0+25.0)+5+0.5),pos,n);
case 3: return judge(floor(sqrt((pos*2.0+8100+3.0*73*73.0/4.0)/3.0)+73/2+0.5),pos,n);
case 4: return judge(floor(sqrt((pos*1.0+891000+1109.0*1109.0/8.0)/2.0)+1109/4+0.5),pos,n);
case 5: return judge(floor(sqrt((pos*2.0+277830000+22217.0*22217.0/20.0)/5.0)+2221.7+0.5),pos,n);
}
}
int calc_digit(int num,int pos)
{
while(--pos) num /= 10;
return num%10;
}
int main()
{
int T;
int posNum;
int maxDigitNum,digitNum;
int pos,strPos;
int beginPos[6] = {0,1,46,9046,1395496,189414496};
int num[6] = {0,1,10,100,1000,10000};
int singleStrPos[6] = {0,1,10,190,2890,38890};
scanf("%d",&T);
while(T--)
{
scanf("%d",&pos);
digitNum = maxDigitNum = 5;
while(pos < beginPos[maxDigitNum]&&maxDigitNum--);
strPos = calc_pos(pos-beginPos[maxDigitNum],maxDigitNum);
while(strPos < singleStrPos[digitNum]&&digitNum--);
posNum = (strPos-singleStrPos[digitNum])/digitNum+num[digitNum];
printf("%d\n",calc_digit(posNum,digitNum-(strPos-singleStrPos[digitNum])%digitNum));
}
return 0;
}