计算大n和k的二项式系数(nCk)
我只是看到了这个问题,却不知道如何解决。您能给我提供算法,C ++代码或想法吗?
这是一个非常简单的问题。给定N和K的值,您需要告诉我们二项式系数C(N,K)的值。您可以放心,K <=
N,并且N的最大值是1,000,000,000,000,000。由于该值可能非常大,因此您需要以1009为模来计算结果。输入
输入的第一行包含测试用例T的数量,最多为1000。接下来的T行中的每一行都由两个以空格分隔的整数N和K组成,其中0 <= K <= N和1 <= N
<= 1,000,000,000,000,000 。输出量
对于每个测试用例,在新行上打印二项式系数C(N,K)以1009为模的值。
输入:
3
3 1
5 2
10 3
输出:
3
10
120
回答:
注意1009是质数。
现在您可以使用卢卡斯定理。
哪个状态:
Let p be a prime.If n = a1a2...ar when written in base p and
if k = b1b2...br when written in base p
(pad with zeroes if required)
Then
(n choose k) modulo p = (a1 choose b1) * (a2 choose b2) * ... * (ar choose br) modulo p.
i.e. remainder of n choose k when divided by p is same as the remainder of
the product (a1 choose b1) * .... * (ar choose br) when divided by p.
Note: if bi > ai then ai choose bi is 0.
这样,您的问题就减少了,可以找到最多为a的选择b形式为a <= 1009和b <= 1009的对数N / log
1009数字(以1009为基的N的位数)的乘积1009。
即使N接近10 ^ 15,这也应该使它更容易。
注意:
对于N = 10 ^ 15,N选择N / 2大于2 ^(100000000000000),这远远超出了无符号长整型。
同样,卢卡斯定理建议的算法为O(log N),这
exponentially
比尝试直接计算二项式系数要快(即使您做了mod1009来处理溢出问题)。
这是我很久以前写的关于二项式的一些代码,您需要做的就是对其进行修改,以进行1009模运算(可能有错误,不一定是推荐的编码样式):
class Binomial{
public:
Binomial(int Max)
{
max = Max+1;
table = new unsigned int * [max]();
for (int i=0; i < max; i++)
{
table[i] = new unsigned int[max]();
for (int j = 0; j < max; j++)
{
table[i][j] = 0;
}
}
}
~Binomial()
{
for (int i =0; i < max; i++)
{
delete table[i];
}
delete table;
}
unsigned int Choose(unsigned int n, unsigned int k);
private:
bool Contains(unsigned int n, unsigned int k);
int max;
unsigned int **table;
};
unsigned int Binomial::Choose(unsigned int n, unsigned int k)
{
if (n < k) return 0;
if (k == 0 || n==1 ) return 1;
if (n==2 && k==1) return 2;
if (n==2 && k==2) return 1;
if (n==k) return 1;
if (Contains(n,k))
{
return table[n][k];
}
table[n][k] = Choose(n-1,k) + Choose(n-1,k-1);
return table[n][k];
}
bool Binomial::Contains(unsigned int n, unsigned int k)
{
if (table[n][k] == 0)
{
return false;
}
return true;
}
以上是 计算大n和k的二项式系数(nCk) 的全部内容, 来源链接: utcz.com/qa/405625.html