在自己看来,思路虽然没错,但总是出现这样那样的细节问题。。。。
题目描述:http://poj.org/problem?id=1019
解题思路:开始是以为第i个数字,结果错了。原来是第i位。。。如题目前80位
11212312341234512345612345671234567812345678912345678910123456789101112345678910
寻找第i位的数字分为四个步骤
1,找大块:大块是112......123456789,112123...100;也就是判断第i位所在序列的最大的数字多少位数字
2,找小块:找到第i位所在的序列,1234..i..,比如第8位在11234这个序列中,第11位在12345这个序列中
3,找数字:找到第i位所在的数字
4,找位:在数字中找到位
代码AC memory:416k time:0ms
代码未优化 第一次写blog。。。
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
//本程序中k是题目中的i
unsigned int cs,sz;
int a[]={0,1,11,192,2893,2889+9000*4+5};
unsigned int erfen(int wei,unsigned int z)//用二分查找法找到i所在的小块序列
{
unsigned int num=(int)pow(10,wei-1),low,high,mid,temp,temp1,temp2;
low=num;
high=num*10-1;
while(low<=high)
{
mid=(low+high)/2;
temp1=(mid-num+1-1)*a[wei]+(mid-num+1-1)*(mid-num+1-2)/2*wei;
temp=(mid-num+1)*a[wei]+(mid-num+1)*(mid-num)/2*wei;
if(temp1<z&&z<=temp)//从找大块取得的位数最小数计算,到i的位数总数z大于前面的序列和,小于等于当前序列和
{
break;
}
else if(z>temp)
{
low=mid+1;
}
else
{
high=mid-1;
}
}
sz=z-((mid-num)*a[wei]+(mid-num)*(mid-num-1)/2*wei);//取得i在序列中的位置
return mid;
}
int wei(int k)//找大块,就是看i所在序列最大数是几位数,返回位数
{
if(k>189414495)
{
cs=189414495;
return 5;
}
else if(k>1395495)
{
cs=1395495;
return 4;
}
else if(k>9045)
{
cs=9045;
return 3;
}
else if(k>45)
{
cs=45;
return 2;
}
else
{
cs=0;
return 1;
}
}
int main(int argc, char** argv) {
unsigned int k,z;
int n,d,i,num,no,i1;
scanf("%d",&n);
while(n--)
{
scanf("%d",&k);
d=wei(k);
z=k-cs;
num=erfen(d,z);
i=d;
while(1)//查找i所在数字的位数
{
if(sz<=(a[i]-i))
i--;
else
{
break;
}
}
sz=sz-a[i]+i;
no=(sz-1)/i;
sz=sz-no*i;
no=(int)pow(10,i-1)+no;//找数字
printf("%d\n",no/(int)pow(10,i-sz)%10);//取位
}
return (EXIT_SUCCESS);
}