將得分的序列化成樣例給的那種表格,發現一行和一列是同時肯定的。這個表格以前是正方形的,後來長寬都減去一,仍是正方形。問題形式是遞歸的。這就啓示咱們能夠把這個正方形\(hash\)起來,直接搜索。ios
平局和勝場能夠很顯然地算出來,spa
\(draws=\frac{(n)(n-1)}{2} \times 3-sum\)code
\(wins=\frac{n(n-1)}{2}-draws\)遞歸
靠這個剪枝。get
注意string
if(rac[now]+(n-to+1)*3<data[now])
不能是hash
if(rac[now]+(win)*3<data[now])
也不能是it
if(rac[now]+(win)*3+drs<data[now])
#include<iostream> #include<cstring> #include<algorithm> #include<cstdio> #include<queue> #include<bitset> #include<vector> #include<map> #include<ctime> #include<cstdlib> #include<set> #include<bitset> #include<stack> #include<list> #include<cmath> using namespace std; #define RP(t,a,b) for(register int (t)=(a),edd_=(b);t<=edd_;++t) #define DRP(t,a,b) for(register int (t)=(a),edd_=(b);t>=edd_;--t) #define ERP(t,a) for(int t=head[a];t;t=e[t].nx) #define Max(a,b) ((a)<(b)?(b):(a)) #define Min(a,b) ((a)<(b)?(a):(b)) #define TMP template<class ccf> #define lef L,R,l,mid,pos<<1 #define rgt L,R,mid+1,r,pos<<1|1 #define midd register int mid=(l+r)>>1 #define chek if(R<l||r<L)return #define all 1,n,1 #define pushup(x) seg[(x)]=seg[(x)<<1]+seg[(x)<<1|1] typedef long long ll; TMP inline ccf qr(ccf k){ char c=getchar(); ccf x=0; int q=1; while(c<48||c>57) q=c==45?-1:q,c=getchar(); while(c>=48&&c<=57) x=x*10+c-48,c=getchar(); if(q==-1) x=-x; return x; } const int maxn=17; ll data[maxn]; ll rac[maxn]; ll n; ll temp[maxn]; map < ll , ll > mp; const ll mod=1e9+7; int f=1; int drs,win; inline ll ha(int x){ int cnt=0; RP(t,x+1,n) temp[++cnt]=data[t]-rac[t]; sort(temp+1,temp+cnt+1); ll ret=0; RP(t,1,cnt) ret=ret*28+temp[t]; //ret=ret*46+dr; //ret=ret*46+win; return ret; } inline void com(int x,int y,int k){ if(k==1) drs--,rac[x]++,rac[y]++; if(k==3) win--,rac[x]+=3; if(k==0) win--,rac[y]+=3; } inline void back(int x,int y,int k){ if(k==1) drs++,rac[x]--,rac[y]--; if(k==3) win++,rac[x]-=3; if(k==0) win++,rac[y]-=3; } inline bool jde(int x,int y,int k){ com(x,y,k); if(rac[x]<0||rac[y]<0||rac[x]>data[x]||rac[y]>data[y]||drs<0||win<0) return 0; return 1; } int dx[]={0,1,3,0}; ll dfs(int now,int to){ if(rac[now]+(n-to+1)*3<data[now])//此處不能是win*3 return 0; if(now==n) return 1; ll ret=0; if(to>n){ //return dfs(now+1,now+2); ret=ha(now); if(mp.find(ret)!=mp.end()) return mp[ret]; else return mp[ret]=dfs(now+1,now+2); } RP(t,1,3){ if(jde(now,to,dx[t])) ret+=dfs(now,to+1); back(now,to,dx[t]);ret%=mod; }return ret; } int main(){ #ifndef ONLINE_JUDGE freopen("in.in","r",stdin); freopen("out.out","w",stdout); #endif n=qr(1); win=(n*(n-1))>>1; drs=0; RP(t,1,n) drs+=(data[t]=qr(1)); drs=win*3-drs; win-=drs; sort(data+1,data+n+1); printf("%lld\n",dfs(1,2)); return 0; }