180 likes | 316 Views
The Primes 解题报告. 00108108 刘国栋 2003.7.6. 题目说明. 用数字填充 5×5 矩阵,使得: 每行 ( 左 -> 右 ) 、每列 ( 上 -> 下 ) 、两对角线 ( 左 -> 右 ) 的五个数字连成五位数的质数 每个质数的数字和为 sum 左上角数字为 digit 质数允许重复 质数不能以 0 开头. 题目说明 —— 例子. digit. sum=11 , digit=1 的一个解如右 左上角为 1 行、列、对角线均为质数 行、列、对角线数字和为 11 最左一列、最上一行不能有 0 质数允许重复: 13331.
E N D
The Primes解题报告 00108108 刘国栋 2003.7.6
题目说明 • 用数字填充5×5矩阵,使得: • 每行(左->右)、每列(上->下)、两对角线(左->右)的五个数字连成五位数的质数 • 每个质数的数字和为sum • 左上角数字为digit • 质数允许重复 • 质数不能以0开头
题目说明——例子 digit • sum=11,digit=1的一个解如右 • 左上角为1 • 行、列、对角线均为质数 • 行、列、对角线数字和为11 • 最左一列、最上一行不能有0 • 质数允许重复:13331
题目说明——输入输出 • 输入:两行 第一行数字和sum 第二行左上角数字digit • 输出: 输出所有可能的解,两个解用空行隔开
解法1:枚举法 • 24重循环,逐个确定矩阵中的每个元素 • 必须是五位数,最左一列、最上一行元素不为0 • 根据素数的限制,最右一列、最下一行不能是偶数(只能取 1 3 7 9,但是这样不太好实现) • 则每个位置的可能取值情况如图
枚举顺序 • 考虑到元素和为sum的限制,某些元素可以由已知元素直接确定 • 适当选择每个元素确定的顺序会减少需要枚举的元素数 • 顺序确定原则:尽可能多的由已知元素确定未知元素 • 右图是一种顺序:
枚举顺序 • 按照上面的顺序,复杂度: 96*108/29 • 右图是另一种顺序:枚举尽可能少的元素 • 按此顺序,复杂度: 96*107/29
素数判断 • 每确定好一个五位数后,都要进行素数判断,需要选择好的算法 • 用通用的素数判断法效率会很低 • 题目限定是五位数,sqrt(100000)=316,小于316的素数有65个,可以记录在数组中,每个素数判断最多需要65步 • 用优化的素数判断法:900MS
解法2:回溯法 • 枚举法是先填表格,在填表的过程中进行质数判断 • 考虑先进行质数判断,然后再填表 • 找到符合条件的五位数: 质数 数字和为sum • 用符合条件的五位数按照适当的顺序填充表格
质数计数 • Pi(n):小于等于n的质数的个数 • Pi(n) ~ n/ln(n) n pi(n) n/ln(n) 10 4 4.3 100 25 21.7 316 65 54.9 1,000 168 144.8 10,000 1229 1085.7 100,000 9592 8685.9 1,000,000 78498 72382.4
质数计数2 • 五位数的质数的个数是 N≈ pi(100,000)-pi(10,000) = 7600 • 实际的数目是8363:N=8363 • 符合数字和为sum的质数的个数: sum=23时最多,有757个
找五位数的算法:顺序扫描,找到的数是有序的找五位数的算法:顺序扫描,找到的数是有序的 • for(int i=10001;i<100000;i++) { if(数字和为sum) if(i为质数) { prime[num++]=i; head[i/10000]++; } } • head[i]记录i开头的数的个数 • 可以用head[i]建立搜索的索引
填充顺序的选择 • 填充第i行记做Hi,填充第j列记做Vj,填充对角线记做D1(左下->右上)D2(左上->右下) • 选择原则: • 尽可能多的前面的数字已经确定(已经排序,搜索快) • 每一步填充不要先确定后面的数字(判断冲突麻烦) • 则可以按照下面的顺序填充: • H1, V1, H2, V2, H3, V3, H4, V4, H5, V5,D1, D2
回溯法实现 • 每一步填充对应一个函数,编程实现非常麻烦 • 填充时不能和已经填上的数字矛盾 • 可以利用已经填好的数字进行剪枝、优化,否则时间开销太大 • 比如当某一行(列)中已经确定了三个元素时,可以先检查其元素和是不是超过sum • 需要判断素数时,可以用后面的优化 • 效果: 530MS
枚举法中素数判断的优化 • 从回溯法得到启发: • 可以预先扫描所有五位数,记录数字和为sum且是素数的所有五位数 • 数组中记录的素数是有序的,素数判断时可以用二分法检索:log2757≈10 • 更进一步:记录符合条件的素数的同时记录第一个数字是i的素数的个数,建立索引,减小搜索范围 • 效果: 370MS
结论 • 一定范围内的数的素数判断,可以用查找代替,以提高效率: • 遍历范围内的数,记录素数, • 记录是有序的,二分法查找 • 填充时选择好的填充顺序非常重要 • 两种方法选择不同的填充方式 • 好的剪枝可以提高效率