0
点赞
收藏
分享

微信扫一扫

poj1019


大致题意:

有一串数字串,其规律为

1 12 123 1234 12345 123456 1234567 12345678 123456789 12345678910 1234567891011 123456789101112······k

输入位置n,计算这一串数字第n位是什么数字,注意是数字,不是数!例如12345678910的第10位是1,而不是10,第11位是0,也不是10。总之多位的数在序列中要被拆分为几位数字,一个数字对应一位。

 

解题思路:

首先建议数学底子不好的同学,暂时放一放这题,太过技巧性了,连理解都很困难

 

模拟分组,把1看做第1组,12看做第2组,123看做第3组……那么第i组就是存放数字序列为 [1,i]的正整数,但第i组的长度不一定是i

 

已知输入查找第n个位的n的范围为(1 ≤ n ≤ 2147483647),那么至少要有31268个组才能使得数字序列达到有第2147483647位

 

注意:2147483647刚好是int的正整数最大极限值( ),所以对于n用int定义就足矣。但是s[31268]存在超过2147483647的位数,因此要用unsigned 或long 之类的去定义s[]

 

详细的解题思路请参照程序的注释。

其中数学难点有2:

(int)log10((double)i)+1

(i-1)/(int)pow((double)10,len-pos)%10

非常技巧性的处理手法,其意义已在程序中标明


//* @author:
 //方法一:



 /**

  * 有一串数字串,其规律为:11212312341234512345612345671234567812345678912345678910123456789101112345678910······



       输入位置,输出对应位置的数字,

       如:输入8,输出2;输入:56,输出0,

       注意:两位数字、三位数字对应位都是分开的,难度在这里,输入范围是

    

   其主要算法如下:

   父数字串------>>子数字串-------->>最简数字串

  */

 public class Main {



/**

*  求数 n 的位数,如:

*  12的位数为2,100的位数为3,,5的位数为1

* @param n

* @return

*/


public static int getWeiShu(int n) {

int weiShu = 0;

while (n != 0) {

n = n / 10;

weiShu++;

}

return weiShu;

}



public static int location(int i) {

// i - 所求序数

// ans - 所求位的数字

// j - 递推定位串

// base - 记录每个串递增的位数

// sum - 记录串的总位数 、 用作计数



int ans;

int j = 1, base, sum = 1;


while (i >= sum) {//如果所求的位置大于数字串的总位数

//将所求的序数减去某一个串的总位数

i -= sum;


j++; // j 记载 下一个串 到哪个数字串了 -- 12...j


//获取某一个数字串的位数

base = getWeiShu(j);

// 该串比上一个串多的字符数 - j 的位数

//其实是某一个数字串的位数如112123,sum在这里表示的是数字串1

//或数字串12,或数字串123的位数

sum += base; // 该串的字符总数

}


// 出口:i >= 0

/**

* 当序数i恰好到某一个数字串就结束了

*/

if (i == 0) {

ans = (j - 1) % 10;

return ans;

}



/**

* 以上代码应该是实现了将i定位到某一个数字串的功能,

* 例如,从112123123412345中找出了i在12345中

* 

*/


sum = 1; // 从串(1...j) 中第一个数开始找

base = 1; // 串中第一个数的位数是 1

while (i >= base) // 求 1...j 串中第 i 个数字

{

i -= base;

sum++;


//base用来记录当前遍历到数组的位数

base = getWeiShu(sum); // sum 的位数

}




/**

* if语句主要用于处理这是已经是没有字数字串的情况

* 即,在12345中找到了某一个数字,或1,或2,或3,

*/

if (i == 0) {

ans = (sum - 1) % 10;

return ans;

}



/**

* 以下代码主要处理:

* 在小字符串中如123456789101112131415中

* 的12中确定到底是哪一个数字

* 

* 对于以下求i的算法,理解如下:

* 

* 

*对于123456789(不可能为1234567891011···,此时的数字串已经为最简数字串,不可能在包含子数字串),

*加入我们要取5,我们通常习惯于%10,-----(但是%10时,我们取的是个位)--------->>所以得把

*5以后的数字都去掉,-----(这时我们习惯采取/10操作)-------->>/10的次数由getWeiShu(sum)-i来决定

*/

j = getWeiShu(sum) - i;

while (j-- > 0) // ans is the ith number of (sum)

{

sum /= 10;

}

ans = sum % 10;

return ans;

}



public static void main(String[] args) {



java.util.Scanner input = new java.util.Scanner(System.in);

int t = input.nextInt(); // test number,测试用例的个数



while (t-- > 0) {

//要求位置的数字

int i = input.nextInt();

System.out.println(location(i));

}

}



 }


举报

相关推荐

0 条评论