2023河南萌新联赛第(五)场:郑州轻工业大学 I - 双指针

2023河南萌新联赛第(五)场:郑州轻工业大学 I - 双指针

时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 262144K,其他语言524288K
64bit IO Format: %lld

题目描述

给定一个数组 a a a 和数组 b b b ,两个数组的长度都为 n n n, 请选择分别两个下标 i , j i, j i,j i , j i, j i,j 满足条件 1 ≤ i < j ≤ n 1 \leq i < j \leq n 1i<jn, 求有多少对 i , j i, j i,j 满足 a i × a j = b i × b j a_i \times a_j = b_i \times b_j ai×aj=bi×bj

输入描述:

本题包含多组数据

第一行包含一个正整数 T T T 1 ≤ T ≤ 1 × 1 0 5 1\leq T \leq 1 \times 10^{5} 1T1×105)。

对于每组数据:

第一行包含一个正整数 n ( 1 ≤ n ≤ 2 × 1 0 5 ) n(1 \leq n \leq 2 \times 10^5 ) n(1n2×105)

接下来 2 2 2

第1行包含 n n n 个整数 a 1 , a 2 , a 3 . . . a n ( 1 ≤ a i ≤ 2 × 1 0 5 ) a_1, a_2, a_3 ... a_n(1 \leq a_i \leq 2\times10^5) a1,a2,a3...an(1ai2×105)

第2行包含 n n n 个整数 b 1 , b 2 , b 3 . . . b n ( 1 ≤ b i ≤ 2 × 1 0 5 ) b_1, b_2, b_3 ... b_n(1 \leq b_i \leq 2\times10^5) b1,b2,b3...bn(1bi2×105)

∑ i = 1 T n ≤ 2 × 1 0 5 \sum_{i=1}^{T} n \leq 2 \times 10^{5} i=1Tn2×105

输出描述:

对于每组数据:

输出一行表示有多少对 i , j i, j i,j 满足 a i × a j = b i × b j a_i \times a_j = b_i \times b_j ai×aj=bi×bj

  • 关键词:思维,STL
  • 给定一个数组 a a a 和数组 b b b,问有多少对 i , j i,j ij 满足 1 ≤ i < j ≤ n 1 ≤ i < j ≤ n 1i<jn 使得 a i × a j = b i × b j a_i × a_j = b_i × b_j ai×aj=bi×bj
  • 将原式转化为 a i / b i = b j / a j a_i/b_i = b_j/a_j ai/bi=bj/aj,令 c i = a i / b i c_i = a_i/b_i ci=ai/bi , d j = b j / a j d_j = b_j/a_j dj=bj/aj,这样问题就转化成有多少对 i i i j j j 满足 1 ≤ i < j ≤ n 1 ≤ i < j ≤ n 1i<jn 使得 c i = d j c_i = d_j ci=dj
  • 使用 m a p map map 分别统计数组 c c c 和数组 d d d 中每个数出现的次数并 计算答案。注意由于 i < j i < j i<j a i / b i a_i/b_i ai/bi = b i / a i b_i/a_i bi/ai 时处理不当答案 可能会有冗余计算,注意避免这种情况。如果担心 d o u b l e double double 精度问题可以用分数代替。注意答案开 l o n g long long l o n g long long

输入

2
5
3 2 2 2 3
3 1 2 4 2
5
2 1 1 1 3
4 2 4 3 1

输出

2
1
import java.io.*;
import java.util.HashMap;

public class Main {
    public static int gcd(int a, int b) {
        return b == 0 ? a : gcd(b, a % b);
    }

    public static void main(String[] args) throws IOException {
        BufferedReader bf = new BufferedReader(new InputStreamReader(System.in));
        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));

        int T = Integer.parseInt(bf.readLine());
        while (T-- > 0) {
            HashMap<String, Integer> cnt = new HashMap<>();
            int n = Integer.parseInt(bf.readLine());
            int[] a = new int[n];
            int[] b = new int[n];
            String[] str = bf.readLine().split(" ");
            for (int i = 0; i < n; i++) {
                a[i] = Integer.parseInt(str[i]);
            }
            str = bf.readLine().split(" ");
            for (int i = 0; i < n; i++) {
                b[i] = Integer.parseInt(str[i]);
            }
            long res = 0;
            for (int i = 0; i < n; i++) {
                int d = gcd(a[i], b[i]);
                a[i] /= d;
                b[i] /= d;
                String s1 = a[i] + " " + b[i];
                String s2 = b[i] + " " + a[i];
                res += cnt.getOrDefault(s2, 0);
                cnt.put(s1, cnt.getOrDefault(s1, 0) + 1);
            }
            bw.write(res + "\n");
        }

        bw.close();
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Wa_Automata

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值