2019年9月 PAT甲级 7-1 Forever 题解

2019年9月 PAT甲级 7-1 Forever 题解

题意

输入N对K和m,要求找到所有K位数满足:
1.该数的和为m;
2.该数+1的和为n;
3.m和n的最大公约数是一个大于2的质数;

思路

K<10,最大为9,暴力枚举是10的9次,肯定超时,需要缩小枚举范围。

看到这题,我觉得一种数学直觉是大家都会有的,那就是:任意一个数p和p+1一般都是互质的吧。事实也是如此(我一时没想到反例)。

这就意味着,要是一个数简单+1,若没有进位,那么肯定无法符合要求,因为这样n和m也只相差一,它们是互质的(最大公约数为1,不是大于2的质数)。于是,我们就知道了,我们要枚举的是有进位的那些数。也就是尾数为9、99、999、9999……的那些数。而且,更有趣的是,我们可以根据尾数情况直接得到n和m的差值!举个例子9+1=10,位数和从9到1,m-n=8;99+1=100,位数和从18到100,m-n=17。(代码里的yes函数就在判断这个)

考虑到位数和的范围是其实很小,是1-90,也就是说m和n都是1-90;那我们就可以直接去算1-90这些数,哪些组合是符合条件3的?可以直接打表看。这就是我下面init函数里做的事儿。处理结果mn[i][j]为true表明(i,j)是符合要求的(m,n)对。事实上,根据m、n的差值和mn数组,可以进一步缩小可能的数位和,m和n的差因为是进位造成的,所以是有限制的,只能是17、26、35、44这些数(可以通过我注释掉的代码验证)。也就是说,我们只需要枚举以99、999、9999、99999为位数的数即可。

那剩下来的任务就是枚举了。为了控制好不同位数9尾数的进位,我们需要对前面剩余x个数位从10的x-1次方(形式为10…0)枚举到10的x次方减2(形式为99…98)。枚举代码在main函数里,草稿纸上写写对应一下下标就出来了。枚举并根据mn数组判断,最后把答案加到set里并输出。

至此,本场考试最难的一道题成功AC!(我没看AC率,做到后面才知道这道题过的人最少)代码如下:

#include <iostream>
#include <string>
#include <cstdio>
#include <memory.h>
#include <algorithm>
#include <cstring>
#include <vector>
#include <map>
#include <queue>
#include <set>
using namespace std;

bool mn[100][100];//[i][j]表示(i,j)是符合要求的数对。 

int gcd(int a,int b){
   //辗转相除法求最大公约数 
	if(b==0)
  • 5
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Steven 周

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值