并箱放行
拼多多 9月6号 笔试真题 第二题
拼多多真题目录点击查看: 拼多多 春招&秋招 笔试真题题库目录|笔试题库 + 算法考点详解
题目内容
江岸货栈的调度员要把待发货物两两并箱。货栈里现有 n n n 件货,第 i i i 件的重量是 w i w_i wi。值班条例规定:只有当两件货的重量之和恰好是装载模数 t t t 的倍数时,这一对才能免检并箱放行。调度员想统计:一共有多少种挑选两件货的方案,能够满足这条免检规则。
货物即使重量相同,也按不同件来区分。选出第 i i i 件与第 j j j 件( i ≠ j i\ne j i=j)算一种方案,与顺序无关,即 ( i , j ) (i,j) (i,j) 和 ( j , i ) (j,i) (j,i) 视为同一种。
约束:
2≤ \le ≤ n n n ≤ \le ≤1000001≤ \le ≤ t t t ≤ \le ≤1000000≤ \le ≤ w i w_i wi ≤ \le ≤1000000000
输入描述
第一行两个整数 n n n 和 t t t(2 ≤ \le ≤ n n n ≤ \le ≤ 100000,1 ≤ \le ≤ t t t ≤ \le ≤ 100000),表示货物件数和装载模数。
第二行 n n n 个整数 w 1 , w 2 , ... , w n w_1,w_2,\ldots,w_n w1,w2,...,wn(0 ≤ \le ≤ w i w_i wi ≤ \le ≤ 1000000000),表示各件货物的重量。
输出描述
输出一个非负整数,表示能够免检并箱的无序配对方案数。
样例1
输入
5 4
1 3 5 7 8
输出
4
说明
各件重量对 4 取余依次为 1 , 3 , 1 , 3 , 0 1,3,1,3,0 1,3,1,3,0。余数 1 1 1 与余数 3 3 3 互补,共 2 × \times × 2 = = = 4 对;余数 0 0 0 只有 1 件,无法自成一对。
样例2
输入
3 7
0 7 14
输出
3
说明
三件重量都是 7 的倍数,任意两件之和仍是 7 的倍数。从 3 件里任选 2 件,方案数为 C 3 2 = 3 C_{3}^{2}=3 C32=3。
样例3
输入
6 4
2 2 2 6 10 14
输出
15
说明
六件重量对 4 取余都是 2,而 2 + + + 2 恰好是 4 的倍数。从 6 件里任选 2 件,方案数为 C 6 2 = 15 C_{6}^{2}=15 C62=15。
题解
思路
解题算法:数学
- 对于每个重量
w[i], 能够配对另一个货物必须满足r = w[i] % t- 另一个货物必须满足
(r + r1) % t == 0=>r1 = (t - r) % t
- 维护
cnt[r]表示之前出现过多少个余数为r的货物。从前往后遍历货物,计算r = w[i] % t, need = (t -r) % t,那么当前货物可以和之前cnt[need]配对。于是ans += cnt[need], cnt[r] ++ - 算法总体时间复杂度为
O(n)
C++
cpp
#include <bits/stdc++.h>
using namespace std;
long long solve(vector<long long>& w, int t) {
vector<long long> cnt(t, 0);
long long ans = 0;
for (long long x : w) {
int r = x % t;
// 互补数
int need = (t - r) % t;
ans += cnt[need];
cnt[r]++;
}
return ans;
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int n,t;
cin >> n >> t;
vector<long long> w(n);
for (int i = 0; i < n; i++) {
cin >> w[i];
}
cout << solve(w, t) << endl;
return 0;
}
java
java
import java.util.*;
public class Main {
static long solve(long[] w, int t) {
long[] cnt = new long[t];
long ans = 0;
for (long x : w) {
int r = (int) (x % t);
// 互补数
int need = (t - r) % t;
ans += cnt[need];
cnt[r]++;
}
return ans;
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int t = sc.nextInt();
long[] w = new long[n];
for (int i = 0; i < n; i++) {
w[i] = sc.nextLong();
}
System.out.println(solve(w, t));
sc.close();
}
}
python
python
def solve(w, t):
cnt = [0] * t
ans = 0
for x in w:
r = x % t
# 互补数
need = (t - r) % t
ans += cnt[need]
cnt[r] += 1
return ans
n, t = map(int, input().split())
w = list(map(int, input().split()))
print(solve(w, t))
javascript
js
const readline = require('readline');
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout
});
const lines = [];
rl.on('line', line => {
lines.push(line);
});
rl.on('close', () => {
let idx = 0;
function solve(w, t) {
const cnt = new Array(t).fill(0);
let ans = 0;
for (const x of w) {
const r = x % t;
// 互补数
const need = (t - r) % t;
ans += cnt[need];
cnt[r]++;
}
return ans;
}
const [n, t] = lines[idx++].split(' ').map(Number);
const w = lines[idx++].split(' ').map(Number);
console.log(solve(w, t));
});
Go
go
package main
import (
"bufio"
"fmt"
"os"
)
func solve(w []int64, t int) int64 {
cnt := make([]int64, t)
var ans int64 = 0
for _, x := range w {
r := int(x % int64(t))
// 互补数
need := (t - r) % t
ans += cnt[need]
cnt[r]++
}
return ans
}
func main() {
in := bufio.NewReader(os.Stdin)
out := bufio.NewWriter(os.Stdout)
defer out.Flush()
var n, t int
fmt.Fscan(in, &n, &t)
w := make([]int64, n)
for i := 0; i < n; i++ {
fmt.Fscan(in, &w[i])
}
fmt.Fprintln(out, solve(w, t))
}