Codeforces Round #728 (Div. 2) B - Pleasant Pairs

B - Pleasant Pairs

Description

You are given an array a1, a2, …, an consisting of n distinct integers. Count the number of pairs of indices (i, j) such that i < j and ai ⋅ aj = i + j.

Input

The first line contains one integer t (1 ≤ t ≤ 10^4) — the number of test cases. Then t cases follow.

The first line of each test case contains one integer n (2 ≤ n ≤ 10^5) — the length of array a.

The second line of each test case contains n space separated integers a1, a2, …, an (1 ≤ ai ≤ 2 ⋅ n) — the array a. It is guaranteed that all elements are distinct.

It is guaranteed that the sum of n over all test cases does not exceed 2 ⋅ 10^5.

Output

For each test case, output the number of pairs of indices (i, j) such that i < j and ai ⋅ aj = i + j.

Example
input

3
2
3 1
3
6 1 5
5
3 1 5 9 2

output

1
1
3

Note

For the first test case, the only pair that satisfies the constraints is (1, 2), as a1 ⋅ a2 = 1 + 2 = 3

For the second test case, the only pair that satisfies the constraints is (2, 3).

For the third test case, the pairs that satisfy the constraints are (1, 2), (1, 5), and (2, 3).

题目大意:

给定数组a,求a中满足i < j 并且满足 ai ⋅ aj = i + j 的元素有几对。

题解:

首先想到用暴力求解,枚举数组中所有的数对逐一进行判断。
其中二重循环的时间复杂度太高(O(n2)),直接交就TLE了。

// 暴力无优化, TLE
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1e6 + 5;
ll a[N];
int main() {
	ios::sync_with_stdio(false);
	ll t;
	cin >> t;
	while (t --) {
		ll n;
		cin >> n;
		for (ll i = 1; i <= n; i ++) cin >> a[i];
		ll cnt = 0;
		for (ll i = 1; i <= n; i ++) // O(n2)
			for (ll j = i + 1; j <= n; j ++)
				if (a[i] * a[j] == i + j) cnt ++;
		cout << cnt << '\n';
	}
	return 0;
}

经过思考后可以发现第二重循环是可以进行优化的。

将需要满足的等式a[i] * a[j] = i + j移项可得 j = a[i] * a[j] - i

其中 a[i]i 是已知的,我们可以枚举 a[j]1, 2, 3… 直到 j > n越界。

对应的循环就是 ja[i] - i开始,步长为 a[i] 的循环。其中要注意 j < i 的情况是不符合要求的,continue掉即可。

经过优化后的二重循环就能顺利AC了。

AC代码:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1e6 + 5;
ll a[N];
int main() {
	ios::sync_with_stdio(false);
	ll t;
	cin >> t;
	while (t --) {
		ll n;
		cin >> n;
		for (ll i = 1; i <= n; i ++) cin >> a[i];
		ll cnt = 0;
		for (ll i = 1; i <= n; i ++) {
			for (ll j = a[i] - i; j <= n; j += a[i]) {
				if (j <= i) continue;
				if (a[i] * a[j] == i + j) cnt ++;
			}
		}
		cout << cnt << '\n';
	}
	return 0;
}
  • 4
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值