4474 Yet Another Multiple Problem(HDU)

题意理解

给定一个数n(0<n<10000),和一组共m个个位数,要求n的倍数不包含m个个位数的最小值,不存在返回-1。

问题分析

用数位BFS搜索算法

转1:个位数0-9共10种,排除m种后还剩10-m种取值,这10-m个数字任意组合后的数是n的最小倍数就是所求的数字。

转2:10-m个数字任意组合可以看成是:1位数字组合,2位数字组合,3位数字组合。。。第一个组合能整除n就是所求的数。但这种组合数字的情况太多,如果不存在这样的数,那么遍历就没有结束状态。

转3:找整除n的规律,大数求余的方法:比如123求5的余数,先计算1%5 = 1,(1×10+2)%5=2,(2×10+3)%5=3。基于这个方法,我们可以按如下顺序搜索,一位数是0,1,2,...,9,然后基于1的两位数10,11,12,...,19,基于2的两位数20,21,22,23,...,29,可以理解为这是一个10-m叉树,每个节点对应数的某一位,树根是最高位树,叶子节点是个位数。

注1:对于终结状态的处理,按照上面方法的搜索,对于每个数的余数,范围在0~n-1之间,如果搜索到某个节点的余数和前面的相同,可以不记录这个节点的数字。因为A<B且A%n = B%n, 那么A×10+C<B×10+C, (A×10+C)%n = (B×10+C)%n。这个过程相当于对树进行了剪枝。终结状态就是遍历完所有的余数1~n-1。0表示整除。

注2:当搜索到整除n时,如何输出这个数?用n长度的数组text记录遍历的顺序,用n长度的数组pre记录节点的双亲。当搜索到整除n时,用pre数组向上找双亲节点,输出从个位到最高位的数字,再把它倒过来就是所求的数。实际是树的双亲表示法。

注3:每个节点的数用‘0’+数值存储,string库拼接倒过来的数,用algorithm的reverse方法将它正过来,再用puts(str.c_str())输出。这样就不用显式使用栈了。

其他

此题没做出来,bfs第一次这个使用,学习了

双亲表示法很管用,解决了问题,很好很好。

算法刷的速度明显慢了,这个月项目做了一个基准集。打算每天晚上做一题。这样下去心里慌的一比。

代码链接

https://github.com/xierensong/learngit/blob/master/hdu/4474/h4474.cpp

猜你喜欢

转载自blog.csdn.net/xiexie1357/article/details/82852036