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


版权声明:本文为博主原创文章,博客地址:https://blog.csdn.net/qq_40433389,未经博主允许不得转载。

1. 题意

这道题目的意思是寻找Forever number. “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.
给定K和m 寻找n和A

2. 题解

一开始拿到这道题,觉得又是和狼人杀一样绕的题目。又有gcd,又有素数,又有各个位数之和。
首先,我用暴力方法,尝试了从 10(k-1) 到10k 之间寻找符合条件的数字,结果后面两个测试点运行超时,也感觉很正常。接着我就做后面三道题,幸好后面三题比较简单。接着又来debug第一题。
我的想法一开始是寻找一个最小和最大的数,再在这个区间进行枚举。但是却一直找不到最小的那个数。后来仔细看了下题目,发现要先寻找质数n,心想着这是一个数学问题,我就分析了n需要满足哪个条件。
因为 A+1的各个位数和为n,A的各个位数和为m;m、n满足最小公约数为质数且大于2。因而A+1必须要有进位,也就是A的低位肯定含有不止一个9。假如含有一个9,A+1的各个位数之和就要减少8,意思m和n需要满足这样子的一个式子:m = n + 9 * t - 1 这边的t是指末位有几个9;
这样子进一步我们就能够列举 从3到m这边满足这样子关系式的n:(m-n+1) % 9 ==0 && isPrime(gcd(m,n))&&gcd(m,n) >2;找到这样子一个n之后,我们再去寻找A。A的寻找,我是从一个最小值开始的,这个最小值的求法也很简单,比如t=3 k =5,也就是末尾有3个9,于是我就从10999 开始寻找,接着每次加上 10t 次方,这样子枚举就不会超时了,而且最后的结果还能遵循 n从小到大,A也从小到大。

3. AC代码

#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<math.h>
#include<string>
using namespace std;


int isPrime(int n) {
	if (n <= 1)
		return 0;
	for (int i = 2; i <= sqrt(n); i++) {
		if (n%i == 0)
			return 0;
	}
	return 1;
}

int gcd(int a, int b) {
	if (b == 0)
		return a;
	else
		return gcd(b, a%b);
}

int digit(int n) {
	string a = to_string(n);
	int sum = 0;
	for (int i = 0; i < a.length(); i++) {
		sum = sum + a[i] - '0';
	}
	return sum;
}
int find_min(int nine, int k) {
	string a;
	for (int i = 0; i < k; i++) {
		if (i == 0)
			a = "1";
		else
			a += "0";
	}
	for (int i = k - 1; i >= k - nine; i--)
		a[i] = '9';
	return stoi(a);
}

int Hash[200];

int main() {
	int n;
	scanf("%d", &n);
	int k, m;
	int com;
	for (int i = 1; i <= n; i++) {
		scanf("%d%d", &k, &m);
		printf("Case %d\n", i);
		int flag = 0;
		if (m <= 9 * k) {
			for (int j = 3; j < m; j++) {
				int d = gcd(j, m);
				if (isPrime(d) && d > 2) {
					if ((m - j + 1) % 9 == 0) {
						int nine = (m - j + 1) / 9;
						int least = find_min(nine, k);
						int maxn = pow(10, k);
						for (int t = least; t < maxn; t+=pow(10,nine) ){
							if (digit(t) == m && digit(t + 1) == j) {
								flag = 1;
								printf("%d %d\n", j, t);
							}
						}
					}
				}
			}
		}
		if (flag == 0)
			printf("No Solution\n");
	}
	system("pause");
	return 0;
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值