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

在这里插入图片描述
在这里插入图片描述
给出一个数的位数,及各位数之和,判断是否是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);
		}
	}
}

猜你喜欢

转载自blog.csdn.net/weixin_45486992/article/details/108391448