查表法:建立大型数组,以空间换时间;
题目:
甲乙两人玩一个游戏,游戏规则为从1开始轮流报数,但如果下一个报的数的十进制表示中含有数字9,或者十进制表示中含有数字9的数的所有倍数都必须跳过否则会输掉游戏。 即两人从1开始轮流交替报数,报数过程中任何一个十进制中含有数字9的数、它的所有倍数都不能报出来。例如,甲同学报了8,由于9不能报,乙同学下一个需要报10;如果甲同学报了17,则由于18 = 9*2, 19中含有数字9,都不能报出,乙同学下一个需要报20。 请你帮助乙同学尽快找出要报出的数字。
输入和输出:
输入:第1行,一个正整数T,表示询问的次数。接下来T行,每行一个正整数x,表示甲同学这一次报出的数字。 输出:共T行,每行一个整数,如果甲同学这次报出的数是不能报出的,输出-1,否则输出乙同学这次该报出的数是多少。
提示:
30%的数据: T ≤ 10, x ≤ 100。 70%的数据: T ≤ 1000, x ≤ 10000。 100%的数据: 1 ≤ T ≤ 2 * 10^5, 1 ≤ x ≤ 10^7
代码:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define SIZE 10000050 //由最大的数据10^7决定数组的size
int N[SIZE] = {0}; //数组下标i代表数字,N[i]为-1时,表示不符合条件,否则N[i]为i,表示符合条件
void Init(int SIZE)
{
//构建数组
int tmp = 0, idx = 0;
for(int i = 1; i <= SIZE; i++ )
{
if(N[i] == -1) continue;//已经确定不符合条件的不再判断
tmp = N[i] = i;//对于未进行判断的,先假定符合,赋值为i
//判断含9
while(tmp)
{
if(tmp % 10 == 9)
{
N[i] = -1;//判断为不符合
break;
}
tmp /= 10;
}
//如果为已经判断不合条件,其倍数一定不符合
if(N[i] == -1)
{
idx = i;
for(int j = 2; ; j++)
{
idx += i; //这里采用了加上本身的方法,判断是否
if(idx > SIZE) break; //注意判断是否超过数组大小不
N[idx] = -1;
}
}
}
}
int main()
{
Init(SIZE);
int n, d;
scanf("%d", &n);
for(int i = 0; i < n; i++)
{
scanf("%d", &d);
if(N[d] == -1)
{
printf("-1\n");
continue;
}
int j = d + 1;
for(; j < _SIZE; j++)
{
if(N[j] == -1) continue;
printf("%d\n", N[j]);
break;
}//搜可报出的数
if(j == SIZE) printf("-1\n"); //超出范围
}
return 0;
}
思路勘误:
(1) 对数字范围不确定,int即可表示所有数字;
(2)对于是否是含有9的数的倍数,在得到含有9的数字的同时就排除了其倍数,比除法判断要好;