【问题标题】:How to calculate the amount of possible numbers between 2 or more set of values that don't exceed a certain amount of value?如何计算不超过一定值的 2 组或更多组值之间的可能数字的数量?
【发布时间】:2014-03-18 18:14:07
【问题描述】:

当我对 pair 的两个元素求和时,如何从一组不超过一定值的 n 值中计算可能的数字对的数量?

例如,如果我们想知道 0.1 到 100 之间的两组值之间的可能组合,我们应该计算 1000 x 1000 等于 100 万,对吗?但是如何从这 100 万个算法中找出不超过 100 个(当你将它们相加时)的组合呢?

例如:

  • 向量 X 和 Y 的范围都在 0.1 和 100 之间(每个 1000 个可能的数字)

  • 元素之和不超过100的对的向量X和Y有哪些可能的组合?

可接受的情况是:

排除的情况如下:

那么对于 3 种情况或 n 种情况呢?

.Net 中是否有任何简单的代码来计算这个?或任何简单的数学公式?

提前致谢

【问题讨论】:

  • 什么是“金额”,请详细描述,最好提供示例输入-> 预期输出(解释)
  • 输出应该是不超过 100 的两组值之间可能组合的数量。例如,如果我们想知道 0.1 和 100 之间的两组值之间的可能组合,我们应该计算像 1000 x 1000 等于 100 万对吗?但是如何在算法中摆脱这 100 万个不超过 100 个(当你把它们相加时)的组合呢?这整天都在燃烧我的大脑 :) 对于 3 组或更多组值呢?也许这是一个简单的计算,我错过了一些非常基本的东西
  • 很高兴您添加了“不超过 100(当您将它们相加时)”的描述。我建议将其添加到问题描述中。应该如何猜测“不超过一定值的 2 组或更多组值之间的可能数字的数量”是什么?这是可怕的措辞。
  • 是的...因为这是一个可怕的问题,没有好词来形容它,只是为了阅读和理解标题你必须烧脑
  • 50+50 是否有效?

标签: .net algorithm math numbers combinations


【解决方案1】:

没那么难:

SortedSet<Tuple<decimal,decimal>> set = new SortedSet<Tuple<decimal, decimal>>();
int n = 0 ;

for ( decimal a = 0.1m ; a <= 100m ; a += 0.1m )
{
  for ( decimal b = 100m - a ; b > 0m ; b -= 0.1m )
  {
    if ( a+b > 100m ) throw new InvalidOperationException();
    ++n ;
    set.Add(new Tuple<decimal,decimal>(a,b)) ;
  }
}

一天结束时,n 是 499,500。

如果不构建 SortedSet 并使用 System.Diagnostics.Stopwatch 对其进行计时,它会在大约 4/100 秒(0.040456 秒)内运行(在调试器中)。构建SortedSet 确实需要更长的时间(在调试器中为 2.47 秒)。

【讨论】:

  • 您能否解释一下我在回答中描述的封闭式公式时为什么要这样做?这是巧合,您也得到了 499 500 的结果吗? :p
  • 这有点像在一个向量上运行循环来计算它的元素。
  • 感谢代码,这正是我所需要的,我尝试了 2 个案例,就像您发布的一样,它看起来工作正常,但问题是我需要一个有 10 个案例的案例(a,b , c, d, e, f, g, h, i, j),我在现有的 fors 中放置了更多的“Fors”,并带有新的变量(c、d、e 等......)但现在这需要永远(40 分钟过去了,“a”变量仍在 0.1 中)有什么已知的方法可以加快速度吗?我在想也许使用 LINQ 有一种最快的方法?但我找不到任何有用的东西......
【解决方案2】:

我将描述如何从两个元素对的排列中排除超过 100 个的对,其中重复由 1000 个元素有序集合组成。然而,如果你想计算这个,或者只是从任意对集合中排除这样的对,这还不清楚。如果稍后是这种情况,那么您必须简单地遍历它们,计算总和并进行比较。


如果你区分

(a, b)(b, a)

这意味着您对重复排列感兴趣。

您可以从 1000 个元素集中制作 1000^2 个这样的 2 个元素对。它们可以重新排序为:

(0.1, 0.1), (0.1, 0.2), (0.1, 0.3), ... , (0.1, 99.8), (0.1, 99.9), (0.1, 100) // 1000
(0.2, 0.1), (0.2, 0.2), (0.2, 0.3), ... , (0.2, 99.8), (0.2, 99.9), (0.2, 100) // 1000
...
(100, 0.1), (100, 0.2), (100, 0.3), ... , (100, 99.8), (100, 99.9), (100, 100) // 1000

很容易看出有 1000 * 1000 个。

现在您可以观察到,当您对它们进行限制以使总和小于或等于 100 时,当我们将它们重新排序为总和时很容易发现一个规则:(a+b) 而不是 (a,b):

(0.2), (0.3), (0.4), ... , (99.9), (100), (100.1)         // 1 is wrong
(0.3), (0.4), (0.5), ... , (100), (100.1), (100.2)        // 2 are wrong
...
(100.1), (100.2), (100.3), ... , (199.8), (199.9), (200)  // 1000 are wrong

数一数?

1000 * 1000 - (1 + 2 + ... + 1000) = 1 000 000 - (1+1000)*1000/2 = 
1 000 000 - 1 001 000 / 2 = 1 000 000 - 500 500 = 499 500

公式1:sum

一般以下公式成立:

p = n^k - [ sum_(k-1)_n + n * ( n^(k-1) - ( n - k + 2))]

地点:

  • p - 元素总和
  • k - 元素对的数量(即 2)
  • n - 向量的大小(即 1000)
  • sum_(k-1)_n - 从 k-1 到 n 的整数之和 = k-1 + k-1+1 + k-1+2 + ... + n = ( k-1 + n) * (n-k+2)/2

如果 n=1000,k=2:p = 1000^2 - sum_(1)_1000 在n=1000,k=3的情况下:p = 1000^3 - [ sum_(2)_1000 + 1000 * ( 1000^2 - 999)]


公式 2:sum = 100 的对数

正如您在 cmets 中所描述的,您实际上对总和等于 100 的对感兴趣,而不是 &lt;= 100。美好的。如果您对sum = 100 的一些配对感兴趣,它是:

p = sum (i)_(k-1)_(n^(k-1)) of [ n^(k-1) - i)]

这是从i = k-1i = n^(k-1) 形式n^(k-1) - i 的表达式的总和

可以简写为:

p = sum (j)_(0)_(n^(k-1) -k + 1) of j

这是从j = 0j = n^(k-1) -k + 1 整数j 的总和。这与以下内容相同:

p = ( 1 + n^(k-1) -k + 1) * ( n^(k-1) -k + 1) / 2   // arithmetic series

无需运行循环,数学很简单; )

【讨论】:

  • 是的或多或少是这样,我需要某种代码,使其不仅适用于 2 个元素,而且适用于更多元素,比如 10 个或更多
  • @MartinVerdas 我提供了公式
  • 我不明白这部分“sum_(k-1)_n - 从k-1到n的整数之和”如何将其放入代码中?
  • 这是整数的总和。对于 k =2,它是 (1+1000)*1000/2,对于 k=3,它是 (2+1000)*999/2。我们在这里使用算术级数和的公式。
  • @MartinVerdas 你有一个完整的答案。我可以向你解释更多吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-12-13
  • 2020-11-30
  • 2016-03-23
  • 1970-01-01
  • 2018-01-29
  • 2019-11-09
  • 2013-09-09
相关资源
最近更新 更多