列表

详情


NC20103. [HNOI2013]比赛

描述

沫沫非常喜欢看足球赛,但因为沉迷于射箭游戏,错过了最近的一次足球联赛。此次联 赛共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

3
-
0
3
C
3
0
-
3

0
3
-
3
但沫沫发现当球队较多时,计算工作量将非常大,所以这个任务就交给你了。请你计算 出可能的比赛过程的数目,由于答案可能很大,你只需要输出答案对10^9+7取模的结果











输入描述

第一行是一个正整数N,表示一共有N支球队。
接下来一行N个非负整数,依次表示各队的最后总得分。
输入保证20%的数据满足N ≤ 4,40%的数据满足N ≤ 6,60%的数据满足N ≤ 8,100%的数据满足3 ≤ N ≤ 10且至少存在一组解。

输出描述

仅包含一个整数,表示答案对10^9+7取模的结果

示例1

输入:

4
4 3 6 4

输出:

3

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++14(g++5.4) 解法, 执行用时: 297ms, 内存消耗: 4344K, 提交时间: 2019-10-29 22:18:27

// luogu-judger-enable-o2
//It is made by M_sea
#include <algorithm>
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <tr1/unordered_map>
#define re register
typedef long long ll;
using namespace std;
using namespace std::tr1;

inline int read() {
    int X=0,w=1; char c=getchar();
    while (c<'0'||c>'9') { if (c=='-') w=-1; c=getchar(); }
    while (c>='0'&&c<='9') X=X*10+c-'0',c=getchar();
    return X*w;
}

const int N=10+10;
const int MOD=1e9+7;
const int BASE=28;

inline int cmp(const int x,const int y) { return x>y; }
inline void add(int& x,int y) { x+=y; if (x>=MOD) x-=MOD; }

int n,s[N],a[N],b[N];
unordered_map<ll,int> mem;
unordered_map<ll,int> vis;
int su,sx,sy;

inline int dfs(int u,int v) { //u VS v
    if (u==n) return 1;
    if (a[u]+3*(n-v+1)<s[u]) return 0;
    int rt=0;
    if (v>n) {
        for (re int i=u+1;i<=n;++i) b[i]=s[i]-a[i];
        sort(b+u+1,b+n+1);
        ll S=0;
        for (re int i=u+1;i<=n;++i) S=S*BASE+b[i];
        if (vis[S]) return mem[S];
        else return vis[S]=1,mem[S]=dfs(u+1,u+2);
    }
    if (a[u]+3<=s[u]&&sx)
        a[u]+=3,--sx,add(rt,dfs(u,v+1)),++sx,a[u]-=3;
    if (a[u]+1<=s[u]&&a[v]+1<=s[v]&&sy)
        ++a[u],++a[v],--sy,add(rt,dfs(u,v+1)),++sy,--a[v],--a[u];
    if (a[v]+3<=s[v]&&sx)
        a[v]+=3,--sx,add(rt,dfs(u,v+1)),++sx,a[v]-=3;
    return rt;
}

int main() {
    n=read();
    for (re int i=1;i<=n;++i) s[i]=read(),su+=s[i];
    sx=su-n*n+n,sy=(su-sx*3)/2;
    sort(s+1,s+n+1,cmp);
    printf("%d\n",dfs(1,2));
    return 0;
}

C++ 解法, 执行用时: 137ms, 内存消耗: 2280K, 提交时间: 2021-10-06 18:25:00

#include<bits/stdc++.h>
#include<unordered_map>
using namespace std;
typedef long long ll;
const int maxn = 15, M = 30;
int a[maxn], b[maxn];
int n;
unordered_map<int, int>mp;
int Hash(int m) {
	int ans = m - 1;
	for (int i = 1; i < m; i++)
		ans = ans * M + b[i];
	return ans;
}
int dfs(int x, int y) {
	if (a[x] > 3 * (x - y)) return 0;
	if (x == y) {
		if (x == 1) return 1;
		for (int i = 1; i < x ; i++) b[i] = a[i];
		sort(b + 1, b + x);
		int h = Hash(x);
		return mp.count(h) ? mp[h] : mp[h] = dfs(x - 1, 1);
	}
	int ans = 0;
	if (a[x] >= 3) {
		a[x] -= 3;
		ans += dfs(x, y + 1);
		a[x] += 3;
	}
    if (a[y] >= 3) {
		a[y] -= 3;
		ans += dfs(x, y + 1);
		a[y] += 3;
	}
	if (a[x] && a[y]) {
		a[x]--, a[y]--;
		ans+=dfs(x, y + 1);
		a[x]++, a[y]++;
	}
	
	return ans;
}
int main() {
	scanf("%d", &n);
	for (int i = 1; i <= n; i++) scanf("%d", &a[i]);
	printf("%d\n", dfs(n, 1));
}

上一题