小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
");
flag = true;
break;
}
}
if (flag == true)
continue;
printf("NO
");
}
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} floor=a-1)
那么有人就一脸懵逼了:
?????
这是什么鬼操作???
首先,我们已知(p=a(a-1))
那么((a-1)<sqrt{p}<a)
此时(lfloor sqrt{p} floor=a-1)
还可以得出(lfloor sqrt{p} floor +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;
}
至此,这篇题解就氵完了