C++ 有效地计算阶乘
我有一个N高达10^5的数组。 我需要解决给定L和R的Q范围查询。C++ 有效地计算阶乘,c++,algorithm,data-structures,combinations,C++,Algorithm,Data Structures,Combinations,我有一个N高达10^5的数组。 我需要解决给定L和R的Q范围查询。 好的,因为根据你的评论,数组中只能有105个元素,这也是数组中每个可能值的最大计数 所以你可以做的一件事就是预先计算所有的阶乘到一个数组中,并使用它们进行计算 也许最好的办法是编写一个元程序,它将这些值构造成C++结构,然后可以在自己的代码段中包含这些值。结构将类似于: unsigned int facMod10p7[] = { 0, 1, 2, : /* whatever (10^5)!
好的,因为根据你的评论,数组中只能有105个元素,这也是数组中每个可能值的最大计数 所以你可以做的一件事就是预先计算所有的阶乘到一个数组中,并使用它们进行计算 也许最好的办法是编写一个元程序,它将这些值构造成C++结构,然后可以在自己的代码段中包含这些值。结构将类似于:
unsigned int facMod10p7[] = {
0,
1,
2,
:
/* whatever (10^5)! % 1000000007 is */
};
一旦有了它,每个阶乘的查找都是O1。要进行查询,只需在数组中从L到R迭代,计算唯一值的数量
最好使用一个映射,其中第一个字段是假定此处为无符号值的值,但您也可以很容易地将此字段设为有符号,第二个字段是它发生的次数
对于{4,2,4}的L2/R4情况,您将得到一个如下的映射:
{ [2] = 1, [4] = 2 }
然后,简单地迭代,查找每个计数的阶乘,并取它们的乘积
由于它是On循环中的O1查找/乘法,因此产生的复杂性将是On
例如,一个Python程序在我的机器上输出前10000个阶乘大约需要30秒才能在我的WSL环境中生成整个表,不一定以其令人眼花缭乱的I/O速度著称,至少在即将发布的下一个版本之前:
real 0m29.137s
user 0m28.438s
sys 0m0.547s
如果您想自己进行测试,代码如下:
print('static unsigned int facMod10p7[] = {\n 0,')
val = 1
mult = 2
for i in range(100000):
print(' {},'.format(val) % 1000000007)
val *= mult
mult += 1
print(');')
让我们考虑一下你的例子:
n = 7
A[n] = {5, 4, 2, 4, 5, 5, 7}
L = 2
R = 4
p = 1000000007
计算启用的[]的直方图H[]
在大小为n的数组中,介于L,R之间的所有值中,其中m是任意值的最大计数
H[2] = 1
H[3] = 0
H[4] = 2
在代码中,类似于:
unsigned int facMod10p7[] = {
0,
1,
2,
:
/* whatever (10^5)! % 1000000007 is */
};
int H[R-L+1],i;
对于i=L,iIs 10^5数组的最大大小或最大元素值?@paxdiablo 10^5是数组的最大大小。元素最多可为10^9所有阶乘均以100000007模计算。这是编程竞赛吗?如果是,请发布一个链接。如果竞赛仍在进行中,请不要询问和回答关于它的问题。关于数组中的查询,请参见示例。查询的答案是一个范围内不同元素计数的阶乘的乘积。10^5!有456574个数字。哎呀。@ggorlen:10^5!%1000000007最多有十个数字:-在任何情况下,这些数字只需要计算一次,并且生成的结构包含在代码中。例如,如果使用MPIR,这将是一个棘手的问题。@alex,在您提出的复杂性中,二次项来自哪里?如果在启用的情况下计算范围内的元素,阶乘查找和乘法现在为O1。这是On的结果。@n.m.,你可能应该把评论指向问题而不是答案。如果某个问题是无效的,那么应该删除它,并附上答案。但是人们,好吧,至少我会按照要求回答问题,因为我对它的有效性没有什么假设,当然,除了质量本身。
m = 2
F[] = { 0!,1!,2! }
F[] = { 0 ,1 ,2 }
j = F[H[0]]*F[H[1]]*F[H[2]]
j = F[1]*F[0]*F[2]
j = 1!*0!*2!
j = 2
// 1 2 3 4 5
H[] = { 0,1,0,2,3 }
m = 3
// 0 1 2 3
F[] = { 1,1,2,6 }
PI(F[H]) = F[0]*F[1]*F[0]*F[2]*F[3]
= 1 * 1 * 1 * 2! * 3!
= 2*6
= 12