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;
}
至此,这篇题解就氵完了
本文作者:W-RB,本文遵循 CC BY-NC 协议,转载请注明原文链接:https://www.cnblogs.com/w-rb/p/13885737.html和作者W-RB,且仅允许在非商业情况下使用