Description
Given a positive integer n, write a program to find out a nonzero multiple m of n whose decimal representation contains only the digits 0 and 1. You may assume that n is not greater than 200 and there is a corresponding m containing no more than 100 decimal digits.
Input
The input file may contain multiple test cases. Each line contains a value of n (1 <= n <= 200). A line containing a zero terminates the input.
Output
For each value of n in the input print a line containing the corresponding value of m. The decimal representation of m must not contain more than 100 digits. If there are multiple solutions for a given value of n, any one of them is acceptable.
Sample Input
2
6
19
0
Sample Output
10
100100100100100100
111111111111111111
就是求一个数的倍数,这个倍数必须是只由0,1组成。且不超过100位。
这里最高位肯定是1,毫无疑问,所以技巧就是搜索。从第二位开始,可能是0也可能是1,那就搜索吧~n的改变:n=n×10+1或者n=n×10。逐次将位数增加,然后对n取余,看看是不是0,如果是0了,那就找到了。
举例6:设这个倍数是k,k初值为1,即最高位。
k=1:1%6=1
k=1*10:10%6=4
k=1*10+1:11%6=5
k=10*10:100%6=4
k=10*10+1:101%6=5
k=11*10:110%6=2
k=11*10+1:111%6=3
……
k=111*10:1110%6=0
结构有点类似于二叉树。左孩子就是尾缀+0,右孩子就是尾缀+1.
但这里用到了取余的技巧。即(a*b)%n = ((a%n)*(b%n))%n。
对上式进行优化就会发现,每次取余得到的数不用非得直接这样求出来(而且k会慢慢变得很大),余数的值等于它父节点余数的值*10+(左孩子+0右孩子+1)。
所以说,对k这样的大数取余,就变成了对它父节点余数的处理。解决了大数问题。
广搜:
#include
#include
using namespace std;
int flag[210];
unsigned long long bfs(int k)
{
unsigned long long x, y, z;
queueq;
q.push(1);
while(!q.empty())
{
x = q.front();
q.pop();
if(x % k == 0)
return x;
y = x * 10;
z = x *10 + 1;
if(!flag[y%k]) //剪枝处理。否则会超时。因为广搜的目标只是找到取余n等于0的那个数,当某个余数出现过时,就不用再入队了,因为它已经证明了这个余数及它后边的那些数都是经过处理了的,肯定不会是要找到的数。
{
q.push(y);
flag[y%k] = 1;
}
if(!flag[z%k])
{
q.push(x * 10 + 1);
flag[z%k] = 1;
}
}
return 0;
}
int main()
{
int k;
while(scanf("%d", &k),k != 0)
{
memset(flag, 0, sizeof(flag));
printf("%lld\n", bfs(k));
}
return 0;
}
深搜:
#include
#include
using namespace std;
int flag, k;
void dfs(unsigned long long x, int s)
{
if(flag)
return;
if(x%k == 0)
{
flag = 1;
cout<<x<<endl;
return;
}
if(s == 19) //待
return;
dfs(x*10, s+1);
dfs(x*10+1, s+1);
}
int main()
{
while(scanf("%d", &k),k != 0)
{
flag = 0;
dfs(1, 0);
}
return 0;
}
优化:
#include
int mod[600000];
int main()
{
int k, i, j;
while(scanf("%d", &k),k != 0)
{
mod[1] = 1;
for(i = 2 ; mod[i-1] % k != 0 ; i++)
mod[i] = (mod[i/2] *10 + i % 2) % k; //有趣的数学问题。解决了寻找父节点和左右孩子加的数不一样的问题。
i--;
j = 0;
while(i)
{
mod[j] = i % 2;
i = i / 2;
j++;
}
for(i = j-1 ; i >= 0 ; i--)
printf("%d", mod[i]);
printf("\n");
}
return 0;
}