链接

题意:

对一个数组a,定义符合条件的二元组(i,j)表示恰好存在k个整数y,满足CF895B XK Segments (思维)_数组
且y为x的倍数,求符合条件的二元组数量。

注意二元组(CF895B XK Segments (思维)_i++_02当且仅当CF895B XK Segments (思维)_算法_03

输入数据第一行是n, x, k,接下来一行有n个数字,第i个代表CF895B XK Segments (思维)_i++_04

分析:

首先我们明确一下 肯定不能出现CF895B XK Segments (思维)_算法_05这样是不合法的情况,所以我们排完序,从大到小分析,这样就会避免这种无效情况了。然后我们看 正常的情况枚举下两端情况:
我们其实就是找出两端之间有多少x的倍数?我们要找有k个倍数组:
我们就可以统计出从1-左端有多少个x的倍数,1-右端有多少x的倍数。
首先看左端,如果整除多一个。因为包括两端。

我们将相等的归为一类。这些可以统一操作,然后将其当成右端计入代价。(右端就是统计1-r_i)有多少x的倍数。
然后再看以其为左端有多少种方案数,(左端就需要上去整。)

///苟利国家生死以,岂因祸福避趋之。
#include <bits/stdc++.h>
using namespace std;
#define ll long long
const int maxn = 2e5 + 7;
const double pi = 3.14159265358979;
ll n,x,y,k;
string str;
ll a[maxn];
map<ll,ll> mp;
int main()
{
cin>>n>>x>>k;
for(int i=1;i<=n;i++){
scanf("%lld",&a[i]);
}
sort(a+1,a+1+n);
ll ans=0;
for(int i=n,j=n;i>=1;i--){
j=i;
while(i>=1&&a[i]==a[j]) i--;
for(int h=j;h>i;h--){
mp[a[h]/x]++;
}
for(int h=j;h>i;h--){
ll num=(a[h]+x-1)/x;
ans+=mp[num+k-1];
}
i++;
}
cout<<ans<<endl;
return 0;
}