给出N个整数的列表A,我们被问到Q查询。每个查询由整数K表示,为此我们需要返回具有恰好K个元素的所有可能子列表的乘积之和。
我们需要以模块100003打印答案。
示例:设N = 3,数组为{1,2,3},并且有2个查询。
查询1:K = 1然后答案是6,因为对于K = 1,可能的子列表是{1},{2},{3}所以答案是1 + 2 + 3 = 6.
查询2:K = 2然后答案是11,因为对于K = 2,可能的子列表是{1,2},{2,3},{3,1}所以答案是(1×2)+(2× 3)+(3×1)= 2 + 6 + 3 = 11。
我的尝试:
#define MOD 100003
unsigned long long ans=0;
unsigned long long mulmod(unsigned long long a,unsigned long long b,unsigned long long c){
unsigned long long x = 0,y=a%c;
while(b > 0){
if(b%2 == 1){
x = (x+y)%c;
}
y = (y*2)%c;
b /= 2;
}
return x%c;
}
void KSubset(unsigned long long *a,unsigned long long n,unsigned long long *s,unsigned long long sindex,unsigned long long index,unsigned long long k){
if (index>n)
return;
if (k==0){
unsigned long long productt = 1;
for(int i=0;i<sindex;i++){
productt=mulmod(productt,s[i],MOD);
}
ans=(ans%MOD + productt%MOD)%MOD;
return ;
}
s[sindex]=a[index];
KSubset(a,n,s,sindex+1,index+1,k-1);
KSubset(a,n,s,sindex,index+1,k);
}
但是由于查询可以达到N和N可以达到3 * 10 ^ 4.那么有没有更好的方法解决这个问题?
答案 0 :(得分:2)
由于{3,1}不是子列表,我将假设您的意思是子集。所有计算都要完成mod 100003;没有问题,因为这里的一切都是代数的。如果展开因式多项式
(1 + 1 x) (1 + 2 x) (1 + 3 x)
其中每个因子对应一个输入值,那么你得到
1 + 6 x + 11 x^2 + 6 x^3,
并且查询q的答案是x ^ q的系数。朴素算法相当于扩展一个广义FOIL method,它需要指数时间。具有二次运行时间的更好的算法是逐个累积因子,具有类似
的循环for (int i = degree; i > -1; i--) coefficient[i + 1] += coefficient[i] * x;
其中x
是下一个值。
答案 1 :(得分:0)
如果您有许多查询,那么您可以为数组生成所有子集,
然后根据查询中的k,您可以选择(某些子集)。
ex:a = {1, 2, 3}
所有子集:{1}, {2}, {3}, {1, 2}, {2, 3}, {1, 3}, {}
当您使用k = 1查询(对所有大小为1的子集求和)时,
k = 2(在大小为2的子集上应用您的逻辑)。
但如果每个阵列只有1个查询,那么另一种算法可能会更好。
答案 2 :(得分:0)
这是一个O(n * log ^ 2 n)解决方案:
1)将其写为多项式(1 + x * a [0])*(1 + x * a [1])* ... *(1 + x * a [n - 1])。现在你需要扩展它以获得每个x度的系数。
2)你可以使用分而治之的方法来计算前半部分和后半部分(递归地)的乘积,而不是天真地乘以它们。现在,您可以使用傅立叶快速变换器快速乘以这两个获得的多项式。
3)T(n)= 2 * T(n / 2)+ n * log n = O(n * log ^ 2 n)。
答案 3 :(得分:-1)
使用STL,您可以:
std::size_t compute(const std::vector<int>& v, std::size_t k)
{
std::vector<int> flags(v.size() - k, 0);
flags.resize(v.size(), 1); // result in {0, .., 0, 1, .., 1} with k numbers 1
std::size_t sum = 0;
do {
std::size_t mul = 1;
for (std::size_t i = 0; i != v.size(); ++i) {
if (flags[i]) {
mul *= v[i];
mul %= 10003;
}
}
sum += mul;
sum %= 10003;
} while (std::next_permutation(flags.begin(), flags.end()));
return sum;
}