这个乱搞题
用hash+set搞
或着DFS即可
#include<cstdio>
#include<vector>
#include<cstring>
#include<algorithm>
#include<set>
#define N 32768
using namespace std;
int a[20];
int num[N+100];
struct Point{
int sum,id;
}p[N+100];
set<unsigned long long>s;
bool cmp(struct Point a,struct Point b){
return a.sum<b.sum;
}
int main(){
int t,T,i,j,n,m;
int sum;
scanf("%d",&T);
for(t=1;t<=T;t++){
scanf("%d",&n);
sum=0;
for(i=0;i<n;i++){
scanf("%d",&a[i]);
sum+=a[i];
}
memset(p,0,sizeof(p));
m=1<<n;
for(i=1;i<m;i++){
for(j=0;j<n;j++)
if(i&(1<<j))
p[i].sum+=a[j];
p[i].id=i;
}
sort(p+1,p+m,cmp);
int ans=0;
s.clear();
int p1=0,p2=0;
for(i=1;i<m && p[i].sum<=sum/3;i++){
if(p[i].sum!=p1){
ans+=s.size();
p1=p[i].sum;
s.clear();
}
for(j=i+1;j<m && p[j].sum<=sum/2;j++){
if((p[i].id&p[j].id)!=0)continue;
if(sum-(p[i].sum+p[j].sum)<p[j].sum)continue;
if(p[i].sum+p[j].sum>sum-(p[i].sum+p[j].sum)){
unsigned long long tem=(unsigned long long)p[j].sum+(unsigned long long)160000*p[j].sum+(unsigned long long)160000*160000*(sum-(p[i].sum+p[j].sum));
s.insert(tem);
}
}
}
ans+=s.size();
printf("%d\n",ans);
}
return 0;
}
但是直接枚举1到3^15是不行的
#include"iostream"
#include"vector"
#include"string"
#include"cstdio"
#include"cstdlib"
#include"cmath"
#include"algorithm"
#include"queue"
#include"cstring"
#include"map"
#include"set"
#include"fstream"
#include"sstream"
#include"numeric"
#include"stack"
#include"iomanip"
#include"bitset"
#include"list"
#include"functional"
#include"utility"
#include"ctime"
typedef long long ll;
#define sz(a) sizeof(a)
#define mp make_pair
#define pb push_back
#define ms(a,i) memset((a),(i),sz(a))
const double eps=1e-5;
const int inf=0x7fffffff;
const int mod=1000000007;
using namespace std;
set<pair<int,pair<int,int> > > S;
int n;
int dat[16];
int sum[3];
int three[16];
int main()
{
int t;
scanf("%d",&t);
three[0]=1;
for(int i=1;i<=15;i++)
three[i]=3*three[i-1];
while(t--)
{
scanf("%d",&n);
for(int i=0;i<n;i++)
scanf("%d",&dat[i]);
S.clear();
ms(sum,0);
for(int i=0;i<three[n];i++)
{
ms(sum,0);
int ii=i;
for(int j=0;j<n;j++)
{
sum[ii%3]+=dat[j];
ii/=3;
}
sort(sum,sum+3);
if(sum[0]+sum[1]>sum[2])
S.insert(mp(sum[0], mp(sum[1],sum[2])));
}
printf("%d\n",S.size());
}
}
写成DFS形式复杂度也是3^15,但是就不用每个状态乘以常数15了
#include<cstdio>
#include<cstring>
#include<set>
#include<algorithm>
using namespace std;
int s[20],res,cas,sum[3];
int n;
set<unsigned long long>S;
void dfs(int x){
int i;
if(x==n){
if(sum[0]>sum[1] || sum[1]>sum[2]) return ;
if(sum[0]+sum[1]>sum[2]){
unsigned long long tem=(unsigned long long)sum[0]+(unsigned long long)160000*sum[1]+(unsigned long long)160000*160000*sum[2];
S.insert(tem);
}
return ;
}
for(i=0;i<3;i++){
sum[i]+=s[x];
dfs(x+1);
sum[i]-=s[x];
}
}
int main(){
int i,t;
scanf("%d",&t);
while(t--){
scanf("%d",&n);
memset(has,0,sizeof(has));
for(i=0;i<n;i++)
scanf("%d",&s[i]);
res=0;
sum[0]=sum[1]=sum[2]=0;
S.clear();
dfs(0);
printf("%d\n",S.size());
}
return 0;
}