按题目要求,求出满足能整除相应n~m之间所有数的最小的整数X。
利用分步取余法取余+dfs,dfs时注意利用一些技巧减少取余算数的次数,否则会超时。
代码如下:
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <cmath>
using namespace std;
int n, m, flag;
char save[32];
void dfs(int cur)
{
if(cur == m + 1)
{
flag = 1;
return ;
}
if(cur < n)
for(int i=0; i<10 && !flag; i++)
{
save[cur] = i;
dfs(cur + 1);
}
else
{
int i = 0;
unsigned long long sum = 0;
for(; i<cur && i<18; i++)
sum=(sum * 10 + save[i]);
sum %= cur;// 每十八位取一次余,而不用每一位都取一次余,减少取余次数。
if(cur > 18)
{
for(; i<cur; i++)
sum=(sum * 10 + save[i]);
}
// 在枚举下一个位置的数字时,可以提前将前面的数字全部算好,下面只枚举一位就好。
for(i=0; i<10 && !flag; i++)
{
int j = (sum * 10 + i) % cur;
if(!j)
{
save[cur] = i;
dfs(cur + 1);
}
}
}
}
int main()
{
#ifdef test
freopen("sample.txt", "r", stdin);
#endif
int t;
scanf("%d", &t);
for(int i=1; i<=t; i++)
{
flag = 0;
scanf("%d%d", &n, &m);
for(int j=1; j<10 && !flag; j++)
{
save[1] = j;
dfs(2);
}
printf("Case %d: ", i);
if(flag)
{
for(int j=1; j<=m; j++)
printf("%d", save[j]);
puts("");
}
else
printf("-1\n");
}
return 0;
}