题目链接:
XK Segments
题意:
给你一个n个元素组成的序列,然后定义(i, j)为一个组合,代表a[i] ~ a[j],且这个组合符合从a[i] 到 a[j]之间有 k 个数是 x 的倍数。a[i] <= a[j] 。 问:满足条件的组合有多少个?
题解:
想明白的话,其实定义的序列(i, j),就是一个由n个元素里面的两个元素组成的区间,在这个区间满足从a[i] 到 a[j]之间有 k 个数是 x 的倍数。所以先把这n个元素排好序,然后对于每一个元素a[i] =》
求第一个大于等于a[i]且是x倍数的数 t = ceil(arr[i] * 1.0 / x) * x
然后求第k个x的倍数 l = t + (k - 1) * x; //这里(k - 1)是由于 t 是第一个x的倍数,再加(k - 1)个就是第k个x的倍数。
同理求第(k + 1)个x的倍数r = t + k * x;
那么对于每一个arr[i]在其对应的 l , r 之间的序列里面元素的个数的总和就是答案。
但是需要注意的是:l 其实准确的说应该等于 = max(t + (k - 1) * x, arr[i]); // 因为在小也要大于等于arr[i]。
AC代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<sstream>
#include<vector>
#include<map>
#include<queue>
#include<stack>
#include<set>
#include<cmath>
#define up(i, x, y) for(int i = x; i <= y; i++)
#define down(i, x, y) for(int i = x; i >= y; i--)
#define MAXN ((int)1e5 + 10)
#define INF 0x3f3f3f3f
using namespace std;
typedef long long ll;
ll arr[MAXN];
int main()
{
ll n, x, k;
scanf("%lld %lld %lld", &n, &x, &k);
up(i, 0, n - 1) scanf("%lld", &arr[i]);
sort(arr, arr + n);
ll ans = 0;
up(i, 0, n - 1)
{
ll t = ceil(arr[i] * 1.0 / x) * x;
ll r = t + k * x;
ll l = max(t + (k - 1) * x, arr[i]);
ll temp = lower_bound(arr, arr + n, r) - lower_bound(arr, arr + n, l);
ans += temp;
}
cout<<ans<<'\n';
}