我有一个问题来自互联网,我有一个N个整数数组,并且必须在给定阵列的左(L)和右段(R)的情况下执行段乘法T次并返回一些给定模数的答案模(M)。
约束
N,T< = 100000
1·; = L< = R< = N
M&LT = 10 ^ 9
和整数< = 100
实施例 -
输入
5(N) 2 5 8 9 4 4(T) 1 2 3 2 3 4 1 1 1 1 5 100000
输出
1 0 0 2880
所以我已经解决了这个问题,但它有点慢,我需要提示来优化我的程序。
#include "stdio.h"
int main(void)
{
int t;
scanf("%d",&t);
int Array[t+1];
for (int i = 1; i <=t; i++)
{
scanf("%d",&Array[i]);
}
int N;
scanf("%d",&N);
for (int i = 0; i <N ; i++)
{
long long a,b,c;
scanf("%lld%lld%lld",&a,&b,&c);
long long Product = 1;
if (c==1)
{
Product = 0;
}
else
{
for (int j = a; j <=b ; j++)
{
Product *= Array[j];
if (Product>=10000000000000000)
{
Product%=c;
}
}
}
Product%=c;
printf("%lld\n",Product );
}
return 0;
}
答案 0 :(得分:2)
你可以为每个小于100的素数p计算一个数组A_p [i],它指出p除了你的数组第i个条目的次数。
然后你可以计算一个二级数组B_p [j],它是i的直到和包括j的A_p [i]的累积和。 (这可以通过递归B_p [i] = B_p [i-1] + A_p [i]在O(n)中完成。)
此辅助数组允许您计算任何范围内每个素数的总功率。例如,如果您想知道素数5在数组条目10到100中出现的次数,您可以计算B_5 [100] -B_5 [10-1]。
因此,对于每个查询,您可以通过将每个素数提高到相应的幂并将结果乘以模M来计算最终答案。请注意,有一种称为exponentiation by squaring的技术可以使计算有效。
如果0是可能的整数,则将0添加到计算中考虑的素数列表中。
请注意,这种使用累积和的方法在许多情况下非常有用。例如,Viola-Jones method for face recognition在2维中使用此技术的一种版本,以便能够有效地计算2d滤镜。