所谓缘分数是指这样一对正整数 a 和 b,其中 a 和它的小弟 a−1 的立方差正好是另一个整数 c 的平方,而 c 正好是 b 和它的小弟 b−1 的平方和。例如 8^3−7^3=169=132,而 13=3^2+2^2,于是 8 和 3 就是一对缘分数。
给定 a 所在的区间 [m,n],是否存在缘分数?
输入格式:
输入给出区间的两个端点 0<m<n≤25000,其间以空格分隔。
输出格式:
按照 a 从小到大的顺序,每行输出一对缘分数,数字间以空格分隔。如果无解,则输出 No Solution
。
输入样例 1:
8 200
输出样例 1:
8 3
105 10
输入样例 2:
9 100
输出样例 2:
No Solution
思考
分析题意,题意很清楚,翻译过来就是,给定一个区间,从中找到符合一定要求的所有整数 ,拿到这样的题目,首先尝试暴力破解
遍历区间所有整数i,计算i和i-1的立方差,最大范围25000^3=1.5625e+14,用int肯定是不够用的,long long 能表示的最大数为9.2233720e+18 。如果这个数是一个平方数,再看这个数的开方,是否能由j和j-1的立方和组成.
#include<iostream>
#include<string>
#include<math.h>
using namespace std;
int main() {
long long m, n, flag = 0;
cin >> m >> n;
for (long long i = m; i <= n; i++) {
long long a = i * i * i - (i - 1) * (i - 1) * (i - 1);
long long sqa = sqrt(a);
if (sqa * sqa == a) {
for (long long j = 1; j < sqa; j++)
if (j * j + (j - 1) * (j - 1) == sqa)
{
cout << i << " " << j << endl;
flag = 1;
}
}
}
if (flag == 0)
cout << "No Solution";
return 0;
}
优化
虽然已经3ms了,但是依旧有进步空间。
其一,int是可以用的,如果用int,是会加快计算速度的。立方差可以写成i^3-(i-1)^3,打开整理可得^3-(i-1)^3=3i^2-3i+1=3*i*i-i*i+1,这样不但可以使用int来计算,而且少几次基本运算,也可以增加可以计算的范围,虽然用不上
其二,每次并不需要从1开始计算,我们设k=^2+(j-1)^2<2*j^2,可以得出,j>sqrt(k/2),所以下标从(int)sqrt(k/2)+1开始即可,这一步还有其他简化方式,比如用map存储已经遍历过得平法和,但是不够简洁。
最后代码如下
#include<iostream>
#include<string>
#include<math.h>
using namespace std;
int main() {
int m, n, flag = 0;
cin >> m >> n;
for (int i = m; i <= n; i++) {
int a = 3 * i * i - 3 * i + 1;
int sqa = sqrt(a);
if (sqa * sqa == a) {//判断a是否是一个平方数
for (int j = (int)sqrt(sqa / 2)+1; j < sqa; j++)
if (j * j + (j - 1) * (j - 1) == sqa)
{
cout << i << " " << j << endl;
flag = 1;
}
}
}
if (flag == 0)
cout << "No Solution";
return 0;
}
题外话
总共就4个结果,建议打表(不是
int result[4][2] = { { 8,3 }, { 105,10 }, { 1456,36 }, { 20273,133 } };