AtCoder题解 —— AtCoder Regular Contest 108 —— A - Sum and Product

题目相关

题目链接

AtCoder Regular Contest 108 A 题,https://atcoder.jp/contests/arc108/tasks/arc108_a

Problem Statement

Given are integers S and P. Is there a pair of positive integers (N,M) such that N+M=S and N×M=P?

Input

Input is given from Standard Input in the following format:

S P

Output

If there is a pair of positive integers (N,M)(N,M) such that N+M=SN+M=S and N×M=PN×M=P, print Yes; otherwise, print No.

Samples1

Sample Input 1

3 2

Sample Output 1

Yes

Explaination

  • For example, we have N+M=3 and N×M=2 for N=1,M=2.

Samples2

Sample Input 2

1000000000000 1

Sample Output 2

No

Constraints

  • All values in input are integers.
  • 1\leq S,P\leq 10^{12}

题解报告

题目翻译

给两个正整数 S, P,问是否存在正整数 N 和 M,满足 N+M=S 和 N*M=P。

题目分析

本题是一个比较简单的数学题。根据题目的要求,我们已知 S 和 P,问是否存在 N 和 M。这样,我们可以写出两个方程。

\left\{\begin{matrix} N+M=S\\ N*M=P \end{matrix}\right.,这样就是一个二元一次方程组,只需要求解这个方程组即可。使用换元法,我们零 M=S-N,带入方程后得到,N*(S-N)=P,利用左手法则,整理后我们得到一个一元二次方程,N^2-S*N+P=0,这样可以通过韦达定理来求解方程的跟。

根据韦达定理,可知 \Delta = b^2-4*a*c \qquad where\quad a=1, b=-S, c=P,即 \Delta =S*S-4*P。根据一元二次方程求根公式,我们知道:

  • \Delta < 0,方程有两个虚数跟。本题不符合要求。
  • \Delta =0,方程有两个相等整数跟。可能符合本题要求。
  • \Delta >0,方程有两个不等的整数跟。可能符合本题要求。

根据一元二次方程求根公式,x_{1,2}=\frac{-b\pm \sqrt{b^2-4*a*c}}{2*a} \qquad where\quad a=1, b=-S, c=P,根据题目提供的数据范围我们知道 b=-S,而 S>0,因此 b>0 的。因此当 \Delta 等于零时候,方程有两个相等的正整数跟。当 \Delta>0,题目要求有两个正整数跟,因此必须满足 (-b- \sqrt{b^2-4*a*c})> 0,也就是 -b> \sqrt{b^2-4*a*c} 即 S>\sqrt{S*S-4*P} 才能有两个正整数跟。

数据范围估计

根据题目提供的数据范围 1\leq S,P\leq 10^{12},我们在计算中需要使用到平方,也就是说,最大的数据为 10^{12}*10^{12}=10^{12+12}=10^{24},这说明超过了 unsigned long long 的范围。哪么怎么办?换一个更大的数据类型就可以了。最简单的方法就是讲所有数据当做 double 来处理,这样就可以解决问题。

总结

本题的难度不大,但是细节比较多。

AC 参考代码

//https://atcoder.jp/contests/arc108/tasks/arc108_a
//A - Sum and Product
#include <iostream>
#include <cmath>
using namespace std;
int main() {
    double s,p;
    cin>>s>>p;
    //n+m=s  m=s-n
    //n*m=p  n*(s-n)=p -n^2+s*n-p=0; n^2-s*n+p=0
    //需要有两个正整数跟,根据韦达定理, b^2-4ac,也就是
    //s*s-4*1*p=s*s+4*p>0
    double delta=s*s-4*p;
    if (delta<0) {
        //虚数根
        cout<<"No\n";
    } else if (0==delta) {
        //相同根
        cout<<"Yes\n";
    } else {
        //计算出根
        double x=(s+sqrt(delta))/2;
        double y=(s-sqrt(delta))/2;
        if (y>0 && x+y==s && x*y==p) {
            cout<<"Yes\n";
        } else {
            cout<<"No\n";
        }
    }

    return 0;
}

写代码的时候,用了比较笨的方法,直接将两个跟计算出来,进行比较。

时间复杂度

O(1)。

空间复杂度

O(1)。

枚举

首先感谢 T_a_r_j_a_n 的评论。本题确实可以换一个思路,就是从 1 到 sqrt(P) 中枚举,是否存在数据满足条件。为什么要开根号,因为我们有一个是乘积,N*M=P。

这里需要特别注意数据范围问题,最大数据为 1e12,超过了 int 可以表示范围,需要使用 long long 进行枚举。

而且使用枚举的方法,可以避免浮点数比较中头大的精度问题。

AC 参考代码

//https://atcoder.jp/contests/arc108/tasks/arc108_a
//A - Sum and Product
//从 1 到 sqrt(P) 中枚举是否存在 N 和 M。
#include <bits/stdc++.h>

using namespace std;

//如果提交到OJ,不要定义 __LOCAL
//#define __LOCAL

int main() {
#ifndef __LOCAL
    //这部分代码需要提交到OJ,本地调试不使用
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
#endif
    long long s,p;
    cin>>s>>p;

    long long t=sqrt(p);
    for (long long i=1; i<=t; i++) {
        long long n=i;
        long long m=s-i;
        if (n*m==p) {
            cout<<"Yes\n";
            return 0;
        }
    }
    cout<<"No\n";

#ifdef __LOCAL
    //这部分代码不需要提交到OJ,本地调试使用
    system("pause");
#endif
    return 0;
}

时间复杂度

O(\sqrt{p}),其实就是 O(\sqrt{n})

空间复杂度

O(1)。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 9
    评论
AtCoder Beginner Contest 134 是一场 AtCoder 的入门级比赛,以下是每道的简要题解: A - Dodecagon 目描述:已知一个正十二边形的边长,求它的面积。 解思路:正十二边形的内角为 $150^\circ$,因此可以将正十二边形拆分为 12 个等腰三角形,通过三角形面积公式计算面积即可。 B - Golden Apple 目描述:有 $N$ 个苹果和 $D$ 个盘子,每个盘子最多可以装下 $2D+1$ 个苹果,求最少需要多少个盘子才能装下所有的苹果。 解思路:每个盘子最多可以装下 $2D+1$ 个苹果,因此可以将苹果平均分配到每个盘子中,可以得到最少需要 $\lceil \frac{N}{2D+1} \rceil$ 个盘子。 C - Exception Handling 目描述:给定一个长度为 $N$ 的整数序列 $a$,求除了第 $i$ 个数以外的最大值。 解思路:可以使用两个变量 $m_1$ 和 $m_2$ 分别记录最大值和次大值。遍历整个序列,当当前数不是第 $i$ 个数时,更新最大值和次大值。因此,最后的结果应该是 $m_1$ 或 $m_2$ 中较小的一个。 D - Preparing Boxes 目描述:有 $N$ 个盒子和 $M$ 个物品,第 $i$ 个盒子可以放入 $a_i$ 个物品,每个物品只能放在一个盒子中。现在需要将所有的物品放入盒子中,每次操作可以将一个盒子内的物品全部取出并分配到其他盒子中,求最少需要多少次操作才能完成任务。 解思路:首先可以计算出所有盒子中物品的总数 $S$,然后判断是否存在一个盒子的物品数量大于 $\lceil \frac{S}{2} \rceil$,如果存在,则无法完成任务。否则,可以用贪心的思想,每次从物品数量最多的盒子中取出一个物品,放入物品数量最少的盒子中。因为每次操作都会使得物品数量最多的盒子的物品数量减少,而物品数量最少的盒子的物品数量不变或增加,因此这种贪心策略可以保证最少需要的操作次数最小。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

努力的老周

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

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

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

打赏作者

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

抵扣说明:

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

余额充值