PAT乙级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
分析:
我的做法如下:
根据位数k,生成下限和上限,比如k=5,区间则为[10000,99999];然后在区间内暴力搜索A、A+1,将整数转换为string求各位数字之和;A和A+1各位数字之和的公约数,既要大于2,又要是个素数;但数据比较多,会超时。
后来看到别人说,根据打表可知所有数末尾都是"99"(没看懂为啥),因此搜索起点变为下限+99,间隔为100;暴力搜索A,通过。
代码:
#include<iostream>
#include<string>
#include<cmath>
#include<algorithm>
using namespace std;
long long gcd(long long t1, long long t2) //求最大公约数
{
return t2 == 0 ? t1 : gcd(t2, t1 % t2);
}
int strsum(long long a)
{
string s = to_string(a);
int sum = 0;
for(int i = 0; i < s.length(); i++)
sum += (s[i] - '0');
return sum;
}
bool isprime(long long n)
{
for(long long i = 2; i <= sqrt(n); i++)
if(n % i == 0)
return false;
return true;
}
struct RESULT
{
int n;
long long A;
};
bool cmp(RESULT r1, RESULT r2)
{
if(r1.n != r2.n) return r1.n < r2.n;
else return r1.A < r2.A;
}
RESULT rs[10000000];
int main()
{
int n;
cin >> n;
for(int i = 0; i < n; i++)
{
int k, m;
cin >> k >> m;
string _min = "1" + string(k-1, '0');
string _max = string(k, '9');
long long min = stoll(_min);
long long max = stoll(_max);
cout << "Case " << i + 1 << endl;
long long cnt = 0;
for(long long j = min + 99; j <= max; j+=100)
{
int sj = strsum(j);
int sj1 = strsum(j+1);
if(sj == m)
{
long long common = gcd(sj, sj1);
if(common > 2 && isprime(common))
{
rs[cnt].n = sj1; rs[cnt].A = j;
cnt++;
}
}
}
if(cnt==0) cout << "No Solution" << endl;
else
{
sort(rs, rs+cnt, cmp);
for(int j = 0;j < cnt; j++)
cout << rs[j].n << " " << rs[j].A << endl;
}
}
return 0;
}
#刷题记录#PAT乙级 文章被收录于专栏
PAT乙级(Basic)刷题记录
正浩创新EcoFlow公司福利 608人发布