0
点赞
收藏
分享

微信扫一扫

PAT-2019年秋季-甲级 7-1 Forever (20 分| 多种方法实现,简单数学,附注释,分析)


写在前面

  • 思路分析
  • ​Forever number​​以99结尾
  • ​Why ?​
  • 降低时间复杂度,避免运行超时
  • 详见原因分析
  • 感觉太菜鸡,手高眼低,导致考的太垃圾
  • 有机会再战,记录下今天所思
  • 后续刷题验证

题目详情

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.

测试用例

input:
2
6 45
7 80

output:
Case 1
10 189999
10 279999
10 369999
10 459999
10 549999
10 639999
10 729999
10 819999
10 909999
Case 2

待验证代码

  • ​是否能成功ac,待验证​

#include <iostream>
#include <cmath>
using namespace std;

bool isprime(int a)
{
if(a<=2) return false;
for(int i=2; i*i<=a; i++)
if(a%i==0) return false;
return true;
}

int gcd(int a, int b)
{
return b==0 ? a : gcd(b, a%b);
}
int sums(int a)
{
int sum = 0;
while(a!=0)
{
sum += (a%10);
a/=10;
}
return sum;
}

int main()
{
int n, k, m;

cin >> n;
for(int i=0; i<n; i++)
{
scanf("%d %d", &k, &m);
printf("Case %d\n", i+1);
int left = pow(10,k-3), right = pow(10,k-2)-1, flag = 0;
for(int i=left; i<=right; i++)
{
int mm = sums(i*100+99), mn = sums(i*100+100);
if(mm==m && isprime(gcd(mm,mn)))
{
printf("%d %d\n", mn, i*100+99);
flag = 1;
}
}
if(!flag)
printf("No Solution\n");
}

return 0;
}

  • 方法2: 公式法
  • 以多少个9结尾
  • ​​PAT2019-秋季甲级题解​​

#define
#include <iostream>
#include <algorithm>
#include <cmath>
#include <string>
#include <set>
#include <vector>
#include <map>
using namespace std;

//思路,来自某大神考完的分享
//考虑m的形状。
//若m的个位数不是9,则n=m+1,则gcd必然为1,不符合大于2素数的要求。
//从而m的个位必然为9。
//若m的十位数不是9,而个位9,则n=m-8
//百位非9,个十为9,则n=m-17
//以此类推,n=m+1-t*9,t为末位连续9的个数。
//找出满足isprime的t,然后逐次找出对应A即可。
//看讨论,大部分人好像是用dfs做的。这个思路比较出彩。

bool isprime(int a)
{
if (a <= 2)
return false; //题目要求大于2的素数,所以判2为不合法
int sqr = sqrt(1.0*a);
for (int i = 2; i <= sqr; i++)
if (a%i == 0)
return false;
return true;
}

int get_sum(int x)
{
int summ = 0;
while (x)
{
summ += x % 10;
x /= 10;
}
return summ;
}

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

int main()
{
int N, k, m, n, t;
cin >> N;
for (int i = 1; i <= N; i++)
{
scanf("%d%d", &k, &m);
int zf = 0;
printf("Case %d\n", i);
for (t = 1; t < k; ++t) //已知个位数必然为9,寻找合法的t值
{
n = m + 1 - t * 9;
if (!isprime(gcd(m, n)))
continue;
int mins = pow(10.0, k-t-1),maxs = pow(10.0, k-t)-1; //对合法的t值进行操作
for (int j = mins; j < maxs; j++)
{
int cur = j * pow(10, t) + pow(10, t)-1;
if (get_sum(cur) == m)
{
zf = 1;
printf("%d %d\n", n, cur);
}
}
}
if (!zf)
printf("No Solution");
}
}

原因分析

  • 前置条件
  • ​K (3<K<10)​
  • ​m (1<m<90)​
  • ​the sum of all the digits of A is m;​
  • ​the sum of all the digits of A+1 is n;​
  • ​the greatest common divisor of m and n is a prime number which is greater than 2.​
  • ​N (≤5)​
  • 分析优化
  • m最大值: 89,n最大值: 90
  • 计算90以内m、n公共最大除数,该除数是大于2的质数
  • m+1必定存在进位,否则无结果
  • 条件转化1:进位等价于计算m以多少个数字​​9​​结尾
  • 条件转化2:x个9结尾,则有​​(m-n+1)%9==0​
  • 最小差值: 17,即以99结尾
  • 计算代码

#include <iostream>
using namespace std;
bool isprime(int a)
{
if(a<=2) return false;
for(int i=2; i*i<=a; i++)
{
if(a%i==0) return false;
}

return true;
}
int gcd(int a, int b)
{
return b==0 ? a: gcd(b, a%b);
}
int main()
{

for(int i=1; i<90; i++)
{
for(int j=i+1; j<90; j++)
{
int gcds = gcd(i,j);
if(isprime(gcds) && (j-i+1)%9==0 )
printf("%d %d %d\n", i,j, j-i);
}
}

return 0;
}

  • 计算结果

5 40 35
5 85 80
7 42 35
10 45 35
11 55 44
13 39 26
14 49 35
15 50 35
17 34 17
20 55 35
21 56 35
25 60 35
28 63 35
30 65 35
33 77 44
34 51 17
39 65 26
40 75 35
42 77 35
45 80 35
49 84 35
50 85 35
51 68 17
68 85 17

其他链接

  • ​​dfs剪枝​​
  • ​​暴力打表​​

举报

相关推荐

0 条评论