题目链接:http://poj.org/problem?id=1019
题目大意:
题目的意思很清楚了,就是把数字的每一位都当成是单个的字母来对待,然后求第i位的数是哪一个。(1<=i<=2^31-1)
题目分析:
仔细观察并通过计算可以得知,想要通过穷举的方式用字符串来处理是行不通的,那就只好乖乖得着规律了。
按照最大数字为1、2、3……的原则进行分组。发现了如下规律:
一位数:
1:1;
12:2;
……
123456789:9;
两位数:
12345678910:11;
1234567891011:13;
……
12345……99:189;
最后发现到了五位数的某一位(大于31000,小于32000)时,总长度就已经超过2^31-1了。因而,数据并不算大,可以解决。按照上述规律,定义f[i]为i第一次出现的下标。
那么就卡出i来,然后计算就可以了!
详细就看代码:
#include<iostream>
#include<cstring>
#include<cstdio>
#include<string>
using namespace std;
#define MAX 2147483647
long long f[];//虽然MAX没有超过int但是所求之数是会超过的 void init()
{
f[]=;
int t=;
for(int i=;i<=;i++)
f[i]=f[i-]+i;
for(int i=;i<;i++)
f[i]=f[i-]+(t+=);
for(int i=;i<;i++)
f[i]=f[i-]+(t+=);
for(int i=;i<;i++)
f[i]=f[i-]+(t+=);
for(int i=;i<;i++)//这个上界很是重要!
f[i]=f[i-]+(t+=);
}
int main()
{
int t,n;
init();
cin>>t;
while(t--)
{
cin>>n;
if(n==)
{
cout<<<<endl;
continue;
}
for(int i=;i<;i++)
if(f[i-]<n&&f[i]>=n)
{
int temp=n-f[i-];//差值
if(temp>)//五位数
{
int t=temp-;
int t2=+(t-)/;
t-=*(t2-);
if(t==)
cout<<t2/<<endl;
if(t==)
cout<<(t2///)%<<endl;
if(t==)
cout<<(t2//)%<<endl;
if(t==)
cout<<(t2/)%<<endl;
if(t==)
cout<<t2%<<endl;
}else
if(temp>)//四位数
{
int t=temp-;
int t2=+(t-)/;
t-=*(t2-);
if(t==)
cout<<t2/<<endl;
if(t==)
cout<<(t2//)%<<endl;
if(t==)
cout<<(t2/)%<<endl;
if(t==)
cout<<t2%<<endl; }else
if(temp>)//三位数
{
int t=temp-;
int t2=+(t-)/;
t-=*(t2-);
//cout<<"t2="<<t2<<" t="<<t<<endl;
if(t==)
cout<<t2/<<endl;
if(t==)
cout<<(t2/)%<<endl;
if(t==)
cout<<t2%<<endl; }else
if(temp>)//二位数
{
int t=temp-;
int t2=+(t-)/;
t-=*(t2-);
if(t==)
cout<<t2/<<endl;
if(t==)
cout<<t2%<<endl;
}else
if(temp>)//一位数
cout<<temp<<endl;
break;
}
}
return ;
}
POJ1019