poj1426
题意:输入一个正整数n,求出大于等于这个数的一个整数m(m只能由1和0组成),使得m能被n整除。要求1<=n<=200, m最多只能为100位数。
方法:同除模定理 + 深度优先 + 剪枝
由于m可以达到100位,所以它是一个大数,如果要用大数的方法处理则会比较麻烦而且速度慢。按照题目要求我们只是求出使得余数为0的m就行了,这里用到同余模定理:
(a*b)%m = (a%m*b%m)%m
(a + b)%m = (a%m + b%m)%m
例如111对7求余==(11*10 + 1)%7 = ((11%7*10%7 )%7 + 1%7)%7,假设我们每次增加一个0或1则能求出个位数加0或加1后的余数,写出函数:
int get_mod(int mod, int pre_resu , int m)
{
return ((pre_resu * (10 % mod)) % mod + m % mod) % mod;
}
接下来是深度优先遍历和剪枝:
1. 当遍历超过100个数的时候返回-1,余数标记置为0,说明这条路不能在100以内得到结果,但该余数并不是得到到结果所以标记设为0,可以走该余数的路
2. 当遍历到已得到的余数时返回0,因为下一个余数是通过当前余数得到的,如果相同,则后续结果相同
3. 当得到余数为0时,结束遍历,返回1,输出结果
4. 其他情况则分别往个位加0和1
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define MAX 1000
int flag[MAX] = {0};
char s[MAX] = {"\0"};
int get_mod(int mod, int pre_resu , int m)
{
return ((pre_resu * (10 % mod)) % mod + m % mod) % mod;
}
int dfs(int mod, int pre_mod, int m, int index)
{
int cur_mod, resu = 0;
cur_mod = get_mod(mod, pre_mod, m);
if(index > 99)
{
return -1;
}
// printf("%s\n", s);
if(flag[cur_mod] != 0)
{
// s[index] = '\0';
return 0;
}
s[index] = m + '0';
flag[cur_mod] = 1;
if(cur_mod == 0){
return 1;
}
resu = dfs(mod, cur_mod, 0, index + 1);
if(resu == 1)
{
return 1;
}
else
{
s[index + 1] = '\0';
if(resu == -1)
{
flag[cur_mod] = 0;
}
resu = dfs(mod, cur_mod, 1, index + 1);
if(resu == 1)
{
return 1;
}
else if(resu == -1)
{
s[index + 1] = '\0';
flag[cur_mod] = 0;
return -1;
}
else{
s[index + 1] = '\0';
return 0;
}
}
}
int main()
{
freopen("input.txt", "r", stdin);
freopen("out.txt", "w", stdout);
int k, n = 0;
while(++n < 201)//scanf("%d", &n) && n)
{
memset(flag, 0, sizeof(int) * MAX);
memset(s, '\0', sizeof(char) * MAX);
k = dfs(n, 0, 1, 0);
printf("%s\n", s);
}
system("pause");
return 0;
}
以下是n=6时的余数情况:
1->4->4return0
->5->2->2return0
->3->0return1