题目来源:Luogu P1102,OJ 1522
解法1:Hash表(取模hash函数+开散列表-拉链法)
#include<iostream>
using namespace std;
const int N = 200005;
const int P = 1000003;
int n,c,x,tot = 0;
long long ans = 0;//1e10要开long long了
struct Node{
int data;
int cnt;
int next;
Node(){
data = 0;
cnt = 0;
next = 0;
}
}node[N];
int head[P] = {0};
void _insert(int x){
int p = head[x%P];
if(p==0){
head[x%P] = ++tot;
node[tot].data = x;
node[tot].cnt ++;
return ;
}
while(p!=0){
if(node[p].data == x) break;
if(node[p].next)
p = node[p].next ;
else break;
}
if(node[p].data == x){
node[p].cnt ++;
}
else{
node[p].next = ++tot;
node[tot].data = x;
node[tot].cnt ++;
}
}
long long find(int k){
int p = head[k%P];
if(p==0) return 0;
while(p!=0){
if(node[p].data == k) break;
if(node[p].next == 0) break;
p = node[p].next ;
}
if(node[p].data == k) return node[p].cnt ;
return 0;
}
long long _solve(int k){
long long cnt1 = find(node[k].data);
long long cnt2 = find(node[k].data+c);
return cnt1*cnt2;
}
int main(){
cin>>n>>c;
for(int i=1;i<=n;i++){
cin>>x;
_insert(x);
}
// for(int i=1;i<=10;i++){
// cout<<"head["<<i<<"]"<<head[i]<<endl;
// }
// for(int i=1;i<=tot;i++){
// cout<<"node["<<i<<"] "<<"data "<<node[i].data<<"cnt "<<node[i].cnt<<endl;
// }
for(int i=1;i<=tot;i++){
ans += _solve(i);
}
cout<<ans<<endl;
return 0;
}
有一些没有搞懂的问题是,an是绝对值小于等于230,那么可能是负数。对负数直接取模,得到的结果还是负数,为什么这里head数组使用的时候并没有CE?(按理说,如果下标为负,应该是会变成非法访问?)那么为了解决负数取模的问题,是否要用abs取绝对值?
解法2:看到有sort(nlogn)+双指针(即可以配对的那一段数组头尾指针相减算长度,复杂度介于nlogn和n2之间?肯定是到不了n2,但是具体多少我也不知道捏)的做法
解法3:可以sort+二分(标准的logn)
解法4:map(………………不是不让用STL吗……)