#include <cstdio>
#include <iostream>
#include <algorithm>
#define LL long long
using namespace std;
int a[4][4005];
int b[2][4005*4005];
int main(){
int n;
while(cin >> n){
for(int i = 0;i < n;i++){
for(int j = 0;j < 4;j++){
scanf("%d",&a[j][i]);
}
}
int cnt1 = 0;
int cnt2 = 0;
for(int i = 0;i < n;i++){
for(int j = 0;j < n;j++){
b[0][cnt1++] = a[0][i] + a[1][j];
}
}
for(int i = 0;i < n;i++){
for(int j = 0;j < n;j++){
b[1][cnt2++] = a[2][i] + a[3][j];
}
}
sort(b[1],b[1]+cnt2);
LL ans = 0;
for(int i = 0;i < cnt1;i++){
ans += upper_bound(b[1],b[1]+cnt2,0-b[0][i]) - lower_bound(b[1],b[1]+cnt2,0-b[0][i]);
}
cout << ans << endl;
}
return 0;
}
折半枚举就是讲原先整体的枚举分成部分枚举,然后再两个部分中利用符合条件的枚举的性质进行优化的
本来想了个用母函数做的,但是做完之后发现超时了;
这样想法本身并没有错误但是这里面会有一个母函数本质的问题,母函数的本质是将所有的序列都生成这时候其实就是相当于穷举了,但是这里面只考虑了0的系数所以这时候母函数就会生成太多的累赘的序列了,所以采用母函数是会超时的。下面是用母函数做的
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <queue>
#include <cmath>
#include <cstring>
#include <stack>
#include <set>
#include <map>
#include <vector>
using namespace std;
#define INF 0x2fffffff
#define LL long long
#define MAX(a,b) ((a)>(b))?(a):(b)
#define MIN(a,b) ((a)<(b))?(a):(b)
int a[4][4005];
int main(){
int t;
int n;
while(scanf("%d",&n)!=EOF){
for(int i = 0;i < n;i++){
for(int j = 0;j < 4;j++){
scanf("%d",&a[j][i]);
}
}
map<int,int> ma;
queue<pair<int,int> > que;
for(int i = 0;i < n;i++){
que.push(make_pair(a[0][i],1));
}
for(int i = 1;i < 4;i++){
for(int j = 0;j < n;j++){
int si = que.size();
for(int k = 0;k < si;k++){
pair<int,int> c = que.front();
que.pop();
que.push(c);
c.first = a[i][j] + c.first;
if(ma.find(c.first) == ma.end()){
ma[c.first] = 0;
}
ma[c.first] += c.second;
}
}
while(!que.empty()) que.pop();
for(map<int,int>::iterator ite = ma.begin();ite != ma.end();ite++){
que.push(make_pair(ite->first,ite->second));
}
if(i != 3)
ma.clear();
}
if(ma.find(0) != ma.end())
printf("%d\n",ma[0]);
else
printf("%d\n",0);
}
return 0;
}
版权声明:本文为博主原创文章,未经博主允许不得转载。
时间: 2024-11-02 17:12:51