给定一个序列有如下特征:
1.S1S2…Sk
2.每一组子序列Sk为:1,2,……,k
例如:11212312341234512345612345671234567812345678912345678910123456789101112345678910 (长度为80)
现给定一个数n,输出上述序列第n个“字符”是多少。
AC/216K/0MS
#include<iostream>
using namespace std;
int c[10]; //存放n的十进制,c[0]记录长度
long long b[35000],a[6];
int m[6]={1,10,100,1000,10000,100000}; //m[i]表示i+1位数字中最小的数
/*计算所有小于等于n并且和n具有相同位数的数组成的序列的总长度*/
int work(int n)
{
c[0]=0;
while(n)
{
c[++c[0]]=n%10;
n/=10;
}
int sum=0;
for(int i=c[0];i>0;i--)
{
int t=c[i];
if(i==c[0]) t--;
sum+=t*m[i-1];
}
return (sum+1)*c[0];
}
/*打表计算序列S1S2...Sk的长度并存入b[k]中*/
void play_table()
{
int i,k=1;
/*a[i]记录所有长度小于等于i的数组成的序列的总长度*/
a[0]=0;
for(i=1;i<6;i++)
{
a[i]=(k*10-k)*i;
a[i]+=a[i-1];
k*=10;
}
b[0]=0;
for(i=1;i;i++)
{
b[i]=work(i);
b[i]+=a[c[0]-1];
b[i]+=b[i-1];
if(b[i]>2147483647) break;
}
}
/*计算m的第n位数字*/
int caclu(int m,int n)
{
c[0]=0;
while(m)
{
c[++c[0]]=m%10;
m/=10;
}
return c[c[0]-n+1];
}
/*计算第n个数字*/
int solve(int n)
{
int i;
for(i=0;i>=0;i++)
if(b[i]<n&&b[i+1]>=n) break;
//满足条件时跳出,位于子序列S(i+1)中
n-=b[i];
for(i=0;i>=0;i++)
if(a[i]<n&&a[i+1]>=n) break;
n-=a[i]; i++;
int ans=m[i-1]+(n-1)/i; //第n个数字是ans的第n-((n-1)/i)*i位数
return caclu(ans,n-((n-1)/i)*i);
}
int main()
{
play_table();
int t,n;
cin>>t;
while(t--)
{
cin>>n;
cout<<solve(n)<<endl;
}
return 0;
}