1104、天长地久
题目描述
-
“天长地久数”是指一个 K 位正整数 A,其满足条件为:A 的各位数字之和为 m,A+1 的各位数字之和为 n,且 m 与 n 的最大公约数是一个大于 2 的素数。本题就请你找出这些天长地久数。
输入输出格式
输入格式:
-
输入在第一行给出正整数 N(≤5),随后 N 行,每行给出一对 K(3<K<10)和 m(1<m<90),其含义如题面所述。
输出格式:
-
对每一对输入的 K 和 m,首先在一行中输出
Case X
,其中X
是输出的编号(从 1 开始);然后一行输出对应的 n 和 A,数字间以空格分隔。如果解不唯一,则每组解占一行,按 n 的递增序输出;若仍不唯一,则按 A 的递增序输出。若解不存在,则在一行中输出No Solution
。
输入输出样式
输入样例: 2 6 45 7 80 输出样例: Case 1 10 189999 10 279999 10 369999 10 459999 10 549999 10 639999 10 729999 10 819999 10 909999 Case 2 No Solution
题目分析
注释写的够详细了,自己看,另外再次表白柳神
代码示例
//此为打表观察法,由打表观察法易知最后两位恒为99
//ps(当时看柳神代码看的一脸懵逼,打表?是什么东西?)
#include <iostream>
#include <string>
using namespace std;
//取数各项之和
int getNum(long long num) {
int sum = 0;
while (num) {
sum += num % 10;
num /= 10;
}
return sum;
}
//取两个数公约数
int get(int x, int y) {
int z = y;
while (x%y != 0){
z = x % y,x = y,y = z;
}
return z;
}
//判断是否为素数
bool IsPrime(int number) {
if (number <= 2) return false;
for (int i = 2; i <= number / 2; i++)
if (number%i == 0) return false;
return true;
}
int main() {
//开始打表
for (long long i = 10000; i < 999999999; i++) {
int number = get(getNum(i), getNum(i + 1));
if (IsPrime(number)) cout << i << endl;
}
return 0;
}
//此为AC代码,个人认为这是笔者写PAT乙到现在最复杂的题目,从来没有写代码超过50行
#include <iostream>
#include <string>
#include <cmath>
#include <algorithm>
#include <vector>
using namespace std;
//因为要比较大小,所以我们先建立一个结构体
struct Node {
int n, num;
//struct的属性是public但是它的方法可是private这里我们搞一个友元让方法可以被外部访问
/*参数类型如果是自定义类型,比如自己定义的结构体,类,
尽管sort函数默认是从小到大排列,但是这里必须要重载比较运算符“ < ”!!!*/
friend bool operator < (Node &a, Node &b) {
if (a.n != b.n) return a.n < b.n;
else return a.num < b.num;
}
};
//判断是否是大于2的素数
bool Is_Prime(int num) {
if (num <= 2) return false;
for (int i = 2; i <= sqrt(num); i++)
if (num%i == 0) return false;
return true;
}
//求两个数的最大公约数
int Get_Number(int num1, int num2) {
int number = num2;
while (num1%num2 != 0) {
number = num1 % num2, num1 = num2, num2 = number;
}
return number;
}
int main() {
int total, K, M;
cin >> total;
for (int i = 1; i <= total; i++) {
vector<Node> Vec;
cout << "Case " << i << endl;
cin >> K >> M;
//最大是k个9如果最大都小于M的话,那么这个数就不存在了
if (K * 9 < M) cout << "No Solution" << endl;
else {
//由打表观察法我们已然得知最后两位数必为99那么我们将之省略即可
int temp = pow(10, K - 2);
//注释是地方是柳神原来的i=temp/10但是我没有看懂,为什么前面的都被排除了,所以我改成了10
for (int i = /*temp / */10; i <= temp; i++) {
int sum1 = 18, sum2 = 0, A = i, A1 = i + 1;
while (A) {
sum1 += A % 10;
A /= 10;
//sum1都比我们输入的各数之和要大了,就没有必要继续算下去了
if (sum1 > M) break;
}
while (A1) {
sum2 += A1 % 10, A1 /= 10;
}
if (sum1 == M && Is_Prime(Get_Number(sum1, sum2))) {
Node node = { sum2,i };
Vec.push_back(node);
}
}
sort(Vec.begin(), Vec.end());
if (Vec.empty()) cout << "No Solution" << endl;
else {
for (auto it = Vec.begin(); it != Vec.end(); it++)
cout << it->n << " " << it->num << "99" << endl;
}
}
}
return 0;
}