PAT 2019年秋季 7-1 Forever (20 分)

"Forever number" is a positive integer A with K digits, satisfying the following constrains:

the sum of all the digits of A is m;
the sum of all the digits of A+1 is n; and
the greatest common divisor of m and n is a prime number which is greater than 2.

Now you are supposed to find these forever numbers.

Input Specification:

Each input file contains one test case. For each test case, the first line contains a positive integer N (≤5). Then N lines follow, each gives a pair of K (3<K<10) and m (1<m<90), of which the meanings are given in the problem description.

Output Specification:

For each pair of K and m, first print in a line Case X, where X is the case index (starts from 1). Then print n and A in the following line. The numbers must be separated by a space. If the solution is not unique, output in the ascending order of n. If still not unique, output in the ascending order of A. If there is no solution, output No Solution.

Sample Input:

2
6 45
7 80

Sample Output:

Case 1
10 189999
10 279999
10 369999
10 459999
10 549999
10 639999
10 729999
10 819999
10 909999
Case 2
No Solution

实现思路:

本题和全排列和N-皇后问题都有点类似,可以归纳为一种类型的题目,都是DFS+剪枝,通过全盘遍历所有可能性然后找规律进行剪枝,本题题目的要求是给出一个K和M,表示要求一个K位数,它的每位数单独加起来总和为M,并且要求这个数加1后的数为num,num的每个位加起来的和为n,要求n和m求出来的最大公因数是大于2的,这样就是一个合法数,然后结果要排序输出。

这种题首先先写递归函数的形参,分别是当前组成的数的位数bit,当前所有位加起来和sum,当前组成的数val,然后递归边界就是sum等于M并且bit等于k的时候。
这里有一个剪枝技巧,当sum>m的时候或者bit>k位或者sum+(k-bit)9<m的时候就退出递归,sum+(k-bit)9<m的原理就是当前组成的数的总和+若剩下所有位都取9的时候加起来总和还是小于m的时候说明无论如何该数都无法组成合法的结果数就退出。

AC代码:

#include <iostream>
#include <cstring>
#include <cmath>
#include <vector>
#include <algorithm>
using namespace std;
typedef pair<int,int> PII;
int num,k,m;
vector<PII> ans;

int gcd(int a,int b) {
	return !b?a:gcd(b,a%b);
}

bool isPrme(int x) {
	if(x<=1) return false;
	int sqr=sqrt(1.0*x);
	for(int i=2; i<=sqr; i++) {
		if(x%i==0) return false;
	}
	return true;
}

int getSum(int x) {
	int sum=0;
	while(x!=0) {
		sum+=x%10;
		x/=10;
	}
	return sum;
}

void DFS(int bit,int sum,int val) {//bit存储当前所处数据的第几位 sum每位总和 val当前组成的数据
	if(sum==m&&bit==k) {
		int n=getSum(val+1),key;
		key=gcd(sum,n);
		if(key>2&&isPrme(key)) {
			ans.push_back({n,val});
		}
	}
	if(sum>m||bit>k||sum+(k-bit)*9<m) return;//剪枝
	for(int i=0; i<=9; i++) {
		DFS(bit+1,sum+i,val*10+i);
	}
}

bool cmp(PII a,PII b) {
	if(a.first!=b.first) return a.first<b.first;
	else return a.second<b.second;
}

int main() {
	cin>>num;
	for(int i=1; i<=num; i++) {
		ans.clear();
		printf("Case %d\n",i);
		scanf("%d%d",&k,&m);
		DFS(0,0,0);
		if(ans.size()==0) printf("No Solution\n");
		else {
			sort(ans.begin(),ans.end(),cmp);
			for(int i=0; i<ans.size(); i++) {
				printf("%d %d\n",ans[i].first,ans[i].second);
			}
		}
	}
	return 0;
}
posted @ 2021-02-20 21:21  coderJ_ONE  阅读(144)  评论(0编辑  收藏  举报