给出一个数的位数,及各位数之和,判断是否是forerver 数。 分析:这里从高位开始,如果左边各位数之和小于等于题目中所给的数字,且当右边所有数均为9时,各位数之和大于所给数字。如给定的位数为5,和为45,则当数字是12xxx,当低位均为9,即12999,各位数之和30依然小于45,说明高位的12应该更大。利用这样的条件进行DFS剪枝。
#include<cstdio> #include<string> #include<cmath> #include<vector> using namespace std; int N, k, m; struct node{ int n, val; friend bool operator < (node a, node b) { if(a.n != b.n) return a.n < b.n; else return a.val < b.val; } }; int gcd(int a, int b) { if(b == 0) return a; else return gcd(b , a % b); } bool isPrime(int x) { if(x <= 2) return false; for(int i = 3; i*i <= x; i++) if(x % i == 0) return false; return true; } int getTotal(int x) { int sum = 0; while(x != 0) { int r = x % 10; sum += r; x /= 10; } return sum; } vector<node> res; void DFS(int num, int sum, int rest_k) { if(rest_k == 0) { if(sum == m) { int n = getTotal(num+1); int r = gcd(m, n); if(isPrime(r)) res.push_back({n, num}); return; } } if(rest_k > 0) { for(int i = 0; i <= 9; i++) { if(sum + i + (rest_k-1)*9 >= m && sum + i <= m) DFS(num*10+i, sum+i, rest_k-1);//低位的数可为0 } } } int main() { scanf("%d", &N); for(int i = 1; i <= N; i++) { scanf("%d%d", &k, &m); printf("Case %d\n", i); res.clear(); for(int i = 1; i <= 9; i++) DFS(i, i, k-1);\\最高位数字不能为0 if(res.size() == 0) printf("No solution\n"); else { for(int i = 0; i < res.size(); i++) printf("%d %d\n", res[i].n, res[i].val); } } }