题意:
问某种 i-j 对的个数; i-j 对满足
枚举 i j ,当 ai < aj 时,[ ai, aj ] 中恰好有 k 个数是 x 的倍数 这样的一组i-j对 就是要找的
思路:
我们可以知道,朴素算法就是枚举 ij 这里明显超时,
我们要注意到这里的限制条件: ai <= aj ,所以我们自然会想到排序;
排序后,对每个 a[i] ,我们就会想,另一个满足条件边界是啥? 然后解法就来了,我们根据 恰好k个 x的倍数,然后可以知道满足条件的右边界的大小范围
这样的话 可用lower_bound (log级)查找方法,得到ai 作为左边界值的时候的可能的i-j对的个数;
复杂度 n * logn;
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<string>
#include<cmath>
#include<set>
#include<queue>
#include<stack>
#include<map>
#define PI acos(-1.0)
#define in freopen("in.txt", "r", stdin)
#define out freopen("out.txt", "w", stdout)
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int maxn = 1e5 + 7, maxd = 1000 + 7;
const ll mod = 1e9 + 7;
const int INF = 0x7f7f7f7f;
int dx[4] = {0, 0, 1, -1};
int dy[4] = {1, -1, 0, 0};
ll n, x, k;
ll a[maxn];
//int sum[maxn] = {0};
int main() {
ios::sync_with_stdio(0);
cin >> n >> x >> k;
for(int i = 1; i <= n; ++i) {
cin >> a[i];
}
sort(a+1, a+1+n);
ll ans = 0;
for(int i = 1; i <= n; ++i) {
ll t1 = a[i]/x*x + ( a[i] % x == 0 ? (k-1)*x : k*x );
int id = lower_bound(a+1,a+1+n, a[i]) - (a);
//cout << id << " +++ " << endl;
int len = ( lower_bound(a+id, a+1+n, t1+x) - lower_bound(a+id, a+1+n, t1) );
//cout << len << " === " << endl;
ans += len;
}
cout << ans << endl;
return 0;
}