YbtOJ20001 立方数差

小w又来氵题解啦~~

链接

戳这里

题目

题目描述

给出一个质数 ,要求你判断这个质数是否是两个立方数的差,即判断是否存在正整数\(a,b\)满足\(a^3-b^3=p\)

输入格式

从文件cubicp.in中读入数据。

多组数据。

第一行给出一个\(T\) ,表示有\(T\)组数据。

接下来\(T\)行,每行一个质数\(p\)

输出格式

输出到文件cubicp.out中。

输出\(T\)行,对于每个数如果是立方差数,输出YES,否则输出NO

样例?不想放了

数据范围

对于\(30\%\)的数据,\(2≤p≤100\);

对于\(60\%\)的数据,\(2≤p≤10^6\)

对于\(100\%\)的数据\(2≤p≤10^{12}\),\(1≤T≤100\),并且保证每个\(p\)均为质数。

思路

看了这道题……很明显,这是一道数学题(你这不是废话吗)。

首先,这里有一个立方差。

由立方差公式:\(a^3-b^3=(a-b)(a^2+ab+b^3)\)

可得:\(p=a^3-b^3=(a-b)(a^2+ab+b^3)\) (字母都一样啊喂!)

\(p\) 为质数

\((a-b)=1\)

这里小w解释一下:因为题目中已经说\(p\)是质数了,所以\((a-b)\)\((a^2+ab+b^2)\)肯定有一个为\(1\)(要是有其他的就不是质数了对吧)

而要是\((a^2+ab+b^2)=1\)的话,我们就会明显地发现:\(a^3-b^3=a-b\)

明显不成立

所以这里只能让\((a-b)=1\)

接着继续:

\(b=a-1\)

这个也不用多说了吧?简易方程五年级下学期谢谢。

然后我们就只需要枚举一个\(a\)\(\frac{p}{2}\)。因为\(p\)最大为\(10^{12}\),所以这里也就是\(10^6\)

这样的话,单次时间复杂度为\(O(\frac{p}{2})\),总共为\(O(\frac{pt}{2})\)

贴下代码:

Code1:

#include <cstdio>
using namespace std;

long long p;
long long t;
bool flag;

inline long long read() {
    long long x = 0, f = 1;
    char ch = getchar();
    while (ch < '0' || ch > '9') {
        if (ch == '-')
            f = -1;
        ch = getchar();
    }
    while (ch >= '0' && ch <= '9') {
        x = (x << 1) + (x << 3) + (ch ^ 48);
        ch = getchar();
    }
    return x * f;
}

int main() {
    freopen("cubicp.in", "r", stdin);
    freopen("cubicp.out", "w", stdout);
    t = read();
    for (int i = 1; i <= t; i++) {
        flag = false;
        p = read();
        for (long long i = 1; i <= 1000000; i++) {
            if (p == (i - 1) * (i - 1) + i * i + i * (i - 1)) {
                printf("YES\n");
                flag = true;
                break;
            }
        }
        if (flag == true)
            continue;
        printf("NO\n");
    }
    return 0;
}

但是!这还远远没有完。虽然刚刚我们的时间复杂度已经可以通过这道题了,但我们可以把单次时间压缩为\(O(1)\)

这个想法来自于lmt(%%%),他写出了比标程还快的程序!

刚刚我们已经推到了\(p=(a^2+ab+b^2)\),并且\(b=a-1\)

那么\(p=(a^2-2ab+b^2+3ab)\)

由完全平方公式\(a^2-2ab+b^2=(a-b)^2\)

可得:\(p=(a-b)^2+3ab\)

\((a-b)=1\)

\(p=1+3ab\)

\(b=a-1\)

\(p=1+3a(a-1)\)

这样的话,如果\((p-1)%3≠0\),也就是说\(p-1\)并不是\(3\)的倍数,这就意味着这个肯定不成立,可以直接输出NO

若成立,那么\(p=3a(a-1)\)

那么\(\lfloor \sqrt{p} \rfloor=a-1\)

那么有人就一脸懵逼了:

?????

这是什么鬼操作???

首先,我们已知\(p=a(a-1)\)

那么\((a-1)<\sqrt{p}<a\)

此时\(\lfloor \sqrt{p} \rfloor=a-1\)

还可以得出\(\lfloor \sqrt{p} \rfloor +1=a\)

这样,我们就无须枚举\(a\),成功把时间降到线性。单次时间复杂度\(O(1)\),总共为\(O(t)\)

Code2

#include <iostream>
#include <cstdio>
#include <cmath>
using namespace std;
int n;
long long p;
int main() {
    freopen("cubicp.in", "r", stdin);
    freopen("cubicp.out", "w", stdout);
    cin >> n;
    for (int i = 1; i <= n; i++) {
        cin >> p;
        p -= 1;
        if (p % 3 != 0) {
            cout << "NO" << endl;
            continue;
        } else {
            p /= 3;
            long long f = sqrt(p);
            if (f * (f + 1) == p) {
                cout << "YES" << endl;
            } else {
                cout << "NO" << endl;
            }
        }
    }
    return 0;
}

至此,这篇题解就氵完了

posted @ 2020-10-27 16:45  W-RB  阅读(332)  评论(0编辑  收藏  举报