4 Values whose Sum is 0

给出四组数a[],b[],c[],d[],求x1+x2+x3+x4=0的方案数。其中x1属于a,x2属于b....


这几天学Linux学累了,找几道算法题做做,毕竟很长时间没写acm程序了,手都生了。起初自己的想法便是将a和b的组合方案数存入一数组中并进行排序,然后枚举c和d构成的方案在相应的数组中查找出现的次数将结果累加到最终结果中。其中自己采用了两种方法来做的<1>二分<2>散列表(注意hash数组开的要大一些,否则在一些方案数太多的时候会TLE,这是程序本身的原因)。做完这题发现acm这东西不能放,得一直练着,好吧,以后争取每天做两道题来保持思维。。。


#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#define  inf 0x3f3f3f3f
//#define  sponge_wxy_code
using namespace std;
/*
const int maxn = 4010;
int a[maxn], b[maxn], c[maxn], d[maxn], arr[maxn*maxn];
int len;
int ans;
*/

const int maxn = 4010;
const int table_size = 10000007;
int a[maxn], b[maxn], c[maxn], d[maxn];
int hash[table_size], mark[table_size], value[table_size];
int ans;

void init_hash() {
    memset(hash, 0, sizeof(hash));
    memset(mark, -1, sizeof(mark));
    memset(value, inf, sizeof(value));
}

int get_key(int val) {
    return (val % table_size + table_size) % table_size;
}

void insert_hash(int val) {
    int pos = get_key(val);
    if(mark[pos] == -1) {
        mark[pos] = 1;
        hash[pos] = 1;
        value[pos] = val;
        return ;
    } else if(value[pos] == val) {
        hash[pos]++;
        return ;
    }
    while((value[pos] != val) && mark[pos] != -1) {
        pos = (pos + 1) % table_size;
    }
    if(mark[pos] == -1) {
        mark[pos] = 1;
        hash[pos] = 1;
        value[pos] = val;
    }
    else {
        hash[pos]++;
    }
    return ;
}

int find_hash(int val) {
    int pos = get_key(val);
    if(mark[pos] == -1) return 0;
    while((value[pos] != val) && mark[pos] != -1) {
        pos = (pos + 1) % table_size;
    }
    if(mark[pos] == -1) return 0;
    return hash[pos];
}

/*
int binary_search_one(int val) {
    int l = 0, r = len - 1;
    int pos = inf;
    while(l <= r) {
        int mid = (l + r) >> 1;
        if(arr[mid] < val) {
            l = mid + 1;
        } else {
            r = mid - 1;
            if(arr[mid] == val) {
                pos = min(pos, mid);
            }
        }
    }
    if(pos == inf) return -1;
    return pos;
}

int binary_search_two(int val) {
    int l = 0, r = len - 1;
    int pos = -inf;
    while(l <= r) {
        int mid = (l + r) >> 1;
        if(arr[mid] > val) {
            r = mid - 1;
        } else {
            l = mid + 1;
            if(arr[mid] == val) {
                pos = max(pos, mid);
            }
        }
    }
    if(pos == -inf) return -1;
    return pos;
}
*/

int main() {

#ifdef sponge_wxy_code
    freopen("aa.in", "r", stdin);
    freopen("bb.out", "w", stdout);
#endif

    int n;
    //int T, n, kcase = 0;
    //scanf("%d", &T);
    while(scanf("%d", &n) != EOF) {
        //if(kcase) puts("");
        //kcase++, ans = 0;
        //scanf("%d", &n);
        ans = 0;
        init_hash();
        for(int i = 0; i < n; ++i) scanf("%d %d %d %d", &a[i], &b[i], &c[i], &d[i]);
        /*
        for(int i = 0; i < n; ++i) {
            for(int j = 0; j < n; ++j) {
                arr[len++] = a[i] + b[j];
            }
        }
        */

        //printf("Length:%d\n", len);
        /*
        sort(arr, arr + len);
        for(int i = 0; i < n; ++i) {
            for(int j = 0; j < n; ++j) {
                int temp = -(c[i] + d[j]);


                int pos1 = binary_search_one(temp);
                if(pos1 == -1) continue;
                int pos2 = binary_search_two(temp);
                ans += (pos2 - pos1 + 1);

                //printf("%d %d %d\n", temp, pos1, pos2);

                //ans += (upper_bound(arr, arr + len, temp) - lower_bound(arr, arr + len, temp));
            }
        }
        */
        for(int i = 0; i < n; ++i) {
            for(int j = 0; j < n; ++j) {
                insert_hash(a[i] + b[j]);
            }
        }
        for(int i = 0; i < n; ++i) {
            for(int j = 0; j < n; ++j) {
                int temp = -(c[i] + d[j]);
                ans += find_hash(temp);
            }
        }
        printf("%d\n", ans);
    }
    return 0;
}






  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值