给定一个数N,有多少对数的平方和小于或等于N
Given a number N how many pairs of numbers have square sum less than or equal to N?
让我们将F(N)定义为不同正整数对的数量(A,B)2+B2≤N和A<B。
如果N=5,则唯一可能的此类对是(1,2)对于N=10而言,该对是两个:和。
此外,对于每一个由两个不同的非零平方和组成的数,我们都有F(13)=3,F.(17)=4、F[(20)=5(20)=5[(25)=6和F-(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-A2),B的下界为:Bmin=A+1。
现在您可以执行以下操作:
- 对A从1迭代到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值了,就可以中断搜索。
我在这里写了一个演示,看起来很有效。
相关文章:
- 如何创建一个CMake变量,除非显式重写,否则使用默认值
- 删除一个线程上有数百万个字符串的大型哈希映射会影响另一个线程的性能
- 为什么两个不同的未命名名称空间可以共存于一个cpp文件中
- 运行同一解决方案的另一个项目的项目
- 挂起和取消挂起一个文件DLL
- 创建一个循环,该循环将输出大于零且小于 60(不包括 60)的所有 5 的倍数
- 在树中查找一个路径/子路径,使权重之和小于给定的整数
- 找到最大.任何给定数字的功率值小于另一个给定数字
- 给定一个 N 个数的序列,提取长度为 K 且范围小于 R 的序列数
- 生成一个小于4位的随机数,但其具有1、2或3位数字的概率相等
- 在C++中获取大于或等于一个双精度的最小浮点值(以及小于或等于一的最大浮点值)
- 编写一个函数,返回一个堆栈,该堆栈包含所有小于给定数字的元素,并且顺序相同
- 如何在小于O(n)的时间内选择std::集合中的一个随机元素
- 是否有一种方法可以正确地比较一个float值是否大于/小于另一个
- 在小于0 (N)的时间内找出点是否在N个(可能重叠)矩形中的一个内
- 创建一个函数,检查一个数组是否有两个相反的元素,复杂度小于n^2.(c++)
- 为什么一个队列的大小会小于一个小数字
- 如何找到小于STL集搜索关键字的第一个值
- 为什么我可以分配一个长度小于数组本身的字符串文字
- 我怎么能找到两个小于一个数字的最大幂没有循环