版权声明:蒻蒟的bolg... https://blog.csdn.net/Rose_max/article/details/85246320
Description
沫沫非常喜欢看足球赛,但因为沉迷于射箭游戏,错过了最近的一次足球联赛。此次联 赛共N支球队参加,比赛规则如下: (1)
每两支球队之间踢一场比赛。 (2) 若平局,两支球队各得1分。 (3) 否则胜利的球队得3分,败者不得分。
尽管非常遗憾没有观赏到精彩的比赛,但沫沫通过新闻知道了每只球队的最后总得分, 然后聪明的她想计算出有多少种可能的比赛过程。
譬如有3支球队,每支球队最后均积3分,那么有两种可能的情况: 可能性1 可能性2 球队 A B C 得分 球队 A
B C 得分 A - 3 0 3 A - 0 3 3 B 0
- 3 3 B 3 - 0 3 C 3 0 - 3 C 0 3 - 3 但沫沫发现当球队较多时,计算工作量将非常大,所以这个任务就交给你了。请你计算
出可能的比赛过程的数目,由于答案可能很大,你只需要输出答案对109+7取模的结果
Input
第一行是一个正整数N,表示一共有N支球队。 接下来一行N个非负整数,依次表示各队的最后总得分。
输入保证20%的数据满足N≤4,40%的数据满足N≤6,60%的数据满足N≤8,100%的数据 满足3≤N≤10且至少存在一组解。
Output
仅包含一个整数,表示答案对10^9+7取模的结果
Sample Input
4
4 3 6 4
Sample Output
3
题解
搜索求方案,操作美如画
从头开始搜每场比赛结果
然后可以获得30分的好成绩
可行性剪枝优化一下
大概就是已经爆掉和全赢也到不了
然后一点柿子
决出胜负的场次设为 ,平的场次设为 ,总分数为
于是有
以及
根据这个可以剪掉胜负场次的胡乱搜
搜完一个人的时候,剩下人还差的分数可以用一个哈希存起来
显然剩下人怎么搞和之前的人没有关系
记忆化一下就过了.
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
#include<queue>
#include<vector>
#include<ctime>
#include<map>
#include<bitset>
#define LL long long
#define mp(x,y) make_pair(x,y)
#define pll pair<long long,long long>
#define pii pair<int,int>
#define ULL unsigned long long
using namespace std;
inline int read()
{
int f=1,x=0;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
int stack[20];
inline void write(int x)
{
if(x<0){putchar('-');x=-x;}
if(!x){putchar('0');return;}
int top=0;
while(x)stack[++top]=x%10,x/=10;
while(top)putchar(stack[top--]+'0');
}
inline void pr1(int x){write(x);putchar(' ');}
inline void pr2(int x){write(x);putchar('\n');}
const int mod=1e9+7;
const LL base=28;
map<LL,int> mp1,mp2;
int a[25],b[15],c[15],sum[15],Q[15],n;
LL ge(int u,int nw)
{
LL ret=nw;
for(int i=u;i<=n;i++)c[i]=Q[i]-sum[i];
sort(c+u,c+1+n);
for(int i=u;i<=n;i++)ret=ret*base+c[i];
return ret;
}
int cnt1,cnt2;
LL dfs(int u,int v,int nw)
{
if(sum[u]>Q[u])return 0;
if(sum[u]+(n-v+1)*3<Q[u])return 0;
if(v==n+1)
{
if(sum[u]!=Q[u])return 0;
if(u==n)return 1;
LL num=ge(u+1,nw);
if(mp2[num])return mp1[num];mp2[num]=1;
return mp1[num]=dfs(u+1,u+2,nw+1);
}
LL ret=0;
if(4*(a[u]+1)<=Q[u]+n-1&&sum[u]+3<=Q[u]&&cnt1)
{
a[u]++;sum[u]+=3;cnt1--;
(ret+=dfs(u,v+1,nw+1))%=mod;
a[u]--;sum[u]-=3;cnt1++;
}
if(4*(a[v]+1)<=Q[v]+n-1&&sum[v]+3<=Q[v]&&cnt1)
{
a[v]++;sum[v]+=3;cnt1--;
(ret+=dfs(u,v+1,nw+1))%=mod;
a[v]--;sum[v]-=3;cnt1++;
}
if(2*b[u]<=3*n-3-Q[u]&&2*b[v]<=3*n-3-Q[v]&&sum[v]+1<=Q[v]&&sum[u]+1<=Q[u]&&cnt2)
{
b[u]++;b[v]++;sum[u]++;sum[v]++;cnt2--;
(ret+=dfs(u,v+1,nw+1))%=mod;
b[u]--;b[v]--;sum[u]--;sum[v]--;cnt2++;
}
return ret;
}
int main()
{
n=read();
int su=0;
for(int i=1;i<=n;i++)
{
Q[i]=read();
su+=Q[i];
}
sort(Q+1,Q+1+n);
cnt1=su-n*(n-1);
cnt2=(su-3*cnt1)/2;
pr2(dfs(1,2,0));
return 0;
}