【发布时间】:2016-04-07 01:12:45
【问题描述】:
给定n个整数和一个整数k,告诉给定n个整数有多少对这样的整数对,使得对中两个元素的和可以被k整除?
我不知道 n 和 k 的界限。因此,为简单起见,假设 n 和 k 不是很大。
不用说,尽可能给出最优解。 (我知道天真的方法:-)! )
【问题讨论】:
标签: algorithm
给定n个整数和一个整数k,告诉给定n个整数有多少对这样的整数对,使得对中两个元素的和可以被k整除?
我不知道 n 和 k 的界限。因此,为简单起见,假设 n 和 k 不是很大。
不用说,尽可能给出最优解。 (我知道天真的方法:-)! )
【问题讨论】:
标签: algorithm
两个数之和是否能被k整除仅取决于它们的余数模k。
因此,如果k 相当小,您可以计算每个可能的余数有多少个数,并从中计算对数。假设k > 0 和所有整数都是非负数
unsigned long long combinations(unsigned k, unsigned long long *arr, unsigned n) {
unsigned long long counts[k] = {0};
unsigned i;
for(i = 0; i < n; ++i) {
++counts[arr[i]%k];
}
// number of pairs where both are divisible by k
unsigned long long combs = counts[0]*(counts[0]-1)/2;
for(i = 1; i < (k+1)/2; ++i) {
combs += counts[i]*counts[k-i];
}
if (k == 2*i) {
combs += counts[i]*(counts[i] - 1)/2;
}
return combs;
}
以O(n+k) 的步骤完成工作。如果n 很小而k 很大,则朴素算法更好。
【讨论】:
counts[0] 用于combs 的初始化,我没有忘记这一点(但我还有一个错字,k-1 而不是k-i)。
除了Daniel Fischer所说的,如果k非常大,可以将数字mod k排序,然后将排序后的列表从两端(处理完0 mod k值后)向中间(k/ 2 模 k)。那是 O(n log n),比 O(n^2) 更好,假设你的幼稚算法真的很幼稚。
【讨论】: