题目描述
给定一个不超过10000的正整数n,问等式ac2+ad3+6abd=2bc2+2bd3+3a2d 有多少组不同的解?其中a,b,c,d均为整数且取值范围是区间[1,n]。若解(a1,b1,c1,d1)和解(a2,b2,c2,d2)相同,则有a1=a2,b1=b2,c1=c2,d1=d2.
输入
输入包含多组数据(不超过100组)。
每组数据一行,仅包含一个整数n。
输出
对于每一组数据的n,输出满足题意的方程解的数目。
样例输入
1
2
样例输出
0
5
来源
2016新生赛
题解
题意很明确,给定一个区间[1,n],问你该区间内有多少个不同的方程解。
显而易见d*d*d若取10000,就是10^12,所以long long存储数据。
这个题我TLE无数遍,要对数卡得无限精细才能AC,大家可以参考我怎么非规范卡时间的。
- 首先都是对a-2b=0,有n/2*n*n个解,因为b最大可以取n/2种,c*d可以取n*n种。
然后对c^2+d^3=3ad进行枚举。
- 枚举方式一:对a,d枚举。
当a枚举1-n个数时,可以限制d的枚举次数,d的最大极限是d=sqrt(3*a);
通过ad可以推出,看c是否符合要求,即c<=n且c是正整数。符合要求则ans+=n;(这里n是b的个数为无限取)。但是如果a为偶数,就会出现重复的,所以要减去一种ans–; - 枚举方式二:对c,d枚举。对d分析,若a=n,c=0时,d取最大极限值,d^3=3ad,d^2<3n即d的最大范围为d=sqrt(3n);对c只能枚举1-n了^_^。第二种方法时间复杂度高一些!
- 不管用方式一还是方式二,最后都要判断a是否为偶数,偶数的情况下就要减一种类,因为不能出现重复相同解。
- 枚举方式一:对a,d枚举。
代码
方式一代码
- 内存:1724
- 耗时:2744
- 语言:C++/Edit
- 代码长度:813 B
#include <iostream>
#include <algorithm>
#include <cmath>
#include <cstdio>
using namespace std;
typedef long long ll;
// (a-2b)(c^2-3ad+d^3)=0
int main()
{
ll n, ans;
while(~scanf("%lld",&n)){
ll a, c, d;
ans = n / 2;//有多少组a=2b的解
ans *= n * n;//a=2b后,因为cd可以任意取1~n,
for(a = 1; a <= n; a++)//对c^2-3ad+d^3=0的解枚举
for(d = 1; d * d < 3 * a; d++){//限制d范围
ll cc = 3 * a * d - d * d * d;
c = sqrt(cc);
//printf("%d %d %d\n",c,d,a);
if(c>=1 && c <= n && cc==c*c){
ans += n;
if(a % 2 == 0)//a为偶数,即减去已算过的a=2b的数
ans--;
}
}
printf("%lld\n",ans);
}
}
方式二代码
- 内存:1724
- 耗时:3896
- 语言:C++/Edit
- 代码长度:908 B
#include <iostream>
#include <algorithm>
#include <cmath>
#include <cstdio>
using namespace std;
typedef long long ll;
// (a-2b)(c^2-3ad+d^3)=0
int main()
{
ll n, ans;
while(~scanf("%lld",&n)){
ll a, c, d;
ans = n / 2;//有多少组a=2b的解
ans *= n * n;//a=2b后,因为cd可以任意取1~n,
ll maxd=sqrt(3*n+1);//3*d-d*d*d<=c*c
for(d = 1; d<=maxd; d++)//限制d范围
for(c = 1; c <= n; c++){//对c^2-3ad+d^3=0的解枚举
a = d * d * d + c * c;
if(a % (3 * d) == 0){
a/=(3 * d);
//printf("%d %d %d\n",c,d,a);
if(a>=1 && a <= n){
ans += n;
if(a % 2 == 0)//a为偶数,即减去已算过的a=2b的数
ans--;
}
}
}
printf("%lld\n",ans);
}
}