让我们将 F(N)定义为不同正整数(A,B)的对数,以便 A 2 + B 2 ≤N和 A< B 。
如果 N = 5 唯一可能的对(1,2) N = 10 这两对是 >(1,2)和(1,3)。
此外,我们有 F(13)= 3 , F(17)= 4 , F(17)= 4 , F(20)= 5 , F(20)= 5 , F(25)= 6 , F(100)= 31 < / em>等等,每个数字是两个不同的非零方块的总和。
到目前为止,我有以下解决方案:
long long SOLVE(lld n)
{
long long x=sqrt(n),up=0;
long long a=x,b=1;
while(abs(a-(b-1))!=1)
{
while(sqr(a)+sqr(b)<=n )
{
b++;
}
up+=(b-1);
a--;
}
b--;
up+=(b*(b+1))/2;
return up;
}
int main()
{
cout<<number(100);
return 0;
}
相同的数字是不可数的,因此(1,1)和(2,2)是无效的元组。 相同但不同的订单只计算一次。因此(1,2)和(2,1)只计算一次。
但是由于 N 的范围是1,我需要一个更有效的算法或公式来计算它。有什么技巧可以让我的代码更有效率吗?
答案 0 :(得分:4)
在伪代码中:
int count=0;
for (smaller=1; ;++smaller)
{
maxlarger = floor(sqrt(N-smaller*smaller));
if (maxlarger <= smaller)
break;
count+=(maxlarger-smaller);
}
return count;
答案 1 :(得分:1)
你不必计算 B 的数量:你可以简单地计算出可能的最大B,这就是 A <的立方数。 / EM>:
B max = sqrt(N-A 2 ), B 的下限是: 乙<子>分钟子> = A + 1
现在您可以执行以下操作:
因此,这引出了以下算法:
lld SOLVE(lld n) {
lld aM=sqrt(n);
lld a=1;
lld res = 0;
for(lld a = 1; a < aM; a++) {
int nB = sqrt(n-a*a)-a;
if(nB > 0) {
res += nB;
} else {
break;
}
}
return res;
}
从那时起,不再能找到 B 值,可以中断搜索。
我在这里写了demo这似乎有效。