题目连接:
http://poj.org/problem?id=1426
题目描述:
给一个200以内的整数n,求一个每一位只含0,1的整数m,满足m是n的倍数。
知识储备:
1.同余模定理
(a*b)%n = (a%n *b%n)%n
(a+b)%n = (a%n +b%n)%n
2.建线段树的过程
解决问题:
如图所示,借助建立线段图,来分析这个问题,模拟双入口的bfs, 由图很容易得到每一位的余数 mod[i]=(mod[i/2]*10+i%2)%n, i为上图中的1,2,3,……(int)log2(i)+1表示从高到低的位数,1表示最高位,当某一个mod[i]=0时,说明最先在这位找到了一个满足条件的且位数最小的数,并且如果i为偶数,说明这位为0,i为奇数说明这位放的是1,i/2返回到它的上一位,如此直至返回到第一位。
总结思考:
用已知数据结构的思想,适当情况下,可以出其不意的巧妙的解题,所以要深刻领悟典型数据结构的思想,并灵活运用它。
#include<iostream>
using namespace std;
int mod[1100000];
int main()
{
int i,j,n,save[110];
while(scanf("%d",&n)&&n) //类比线段树的建立
{
mod[1]=1%n; //如果n是1的话,此时其为零
for(i=2;mod[i-1]!=0;i++) //用i的值来确定,0还是1
{
mod[i]=(mod[i/2]*10+i%2)%n; //同余定理+类似双口的Bfs i是偶数就放0,i是奇数就放1
}
i--;
j=0;
while(i)
{
save[j++]=i%2; //从头开始存低位
i=i/2;
}
for(i=j-1;i>=0;i--)
{
printf("%d",save[i]); //从尾开始从高位读
}
putchar('\n');
}
}