给定一个数N,有多少对数的平方和小于或等于N

Given a number N how many pairs of numbers have square sum less than or equal to N?

本文关键字:小于 一个 多少      更新时间:2023-10-16

让我们将F(N)定义为不同正整数对的数量(A,B)2+B2≤NA<B

如果N=5,则唯一可能的此类对是(1,2)对于N=10而言,该对是两个:

此外,对于每一个由两个不同的非零平方和组成的数,我们都有F(13)=3F.(17)=4F[(20)=5(20)=5[(25)=6F-(100)=31等等。

到目前为止,我有以下解决方案:

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)。相同的组合但不同的订单只计数一次。因此,(1,2)

但由于N的范围是1,我需要一个更有效的算法或公式来计算这一点。有什么技巧可以让我的代码更有效率吗?

在伪代码中:

int count=0;
for (smaller=1; ;++smaller)
{
    maxlarger = floor(sqrt(N-smaller*smaller));
    if (maxlarger <= smaller)
        break;
    count+=(maxlarger-smaller);
}
return count;

您不必计算B的数量:您可以简单地计算出最大的B,这是可能的,它立即是A:的元组数量

Bmax=sqrt(N-A2B的下界为:Bmin=A+1

现在您可以执行以下操作:

  • A1迭代到sqrt(n)
  • 对于每个这样的A,计算您可以使用的B的数量
  • 计算这些的总和

这就引出了以下算法:

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值了,就可以中断搜索。

我在这里写了一个演示,看起来很有效。

相关文章: