话说好久没写题(解)了。。

先贴份题解:http://wjmzbmr.com/archives/hnoi-2013-%E9%A2%98%E8%A7%A3/(LJ神题解。。Lazycal表示看不懂。。)

以下是Lazycal's题解:

[bzoj3139][Hnoi2013]比赛

对于一个得分序列,可以发现不论如何排列,答案都是一样的。而且n的得分序列可以由n-1的推来。于是,我们可以搜索第一个队伍与其他队伍的比赛结果,由比赛结果得出n-1支队伍的得分序列,递归搜索。然后用每个队伍的得分和队伍个数作为状态,对每个状态进行压缩,利用最小表示法。由于每个队伍最多只能得27分,所以状态总数不超过28^9/(9!)*2(因为只能存在一个0)为千万级别,可以接受。 

 

/**************************************************************
    Problem: 3139
    User: lazycal
    Language: C++
    Result: Accepted
    Time:732 ms
    Memory:1868 kb
****************************************************************/
 
#include <cstdio>
#include <algorithm>
#include <functional>
#include <map>
const int MOD=1000000000+7;
int n;
std::map<long long,long long>Map;
struct Status
{
    int a[11];
    long long hash()
    {
        long long res=0;
        for (int i=0;i<=n;++i) res=res*28+a[i];
        return res;
    }
    void sort()
    {
        std::sort(a+n-a[0]+1,a+1+n/*,std::greater<int>()*/);
    }
}start,bound;
long long dfs(const int step,Status now)
{
    if (now.a[0] == 1) return Map[now.hash()]=-1;
    if (now.a[n-now.a[0]+1] > 3*(n-step+1)) return -1;
    if (step > n) {
        --now.a[0];
        now.sort();
        if (Map[now.hash()]) return Map[now.hash()];
        return dfs(n-now.a[0]+2,now);
    }
    long long res=0,tmp;
    int idx=n-now.a[0]+1;
    if (now.a[idx] >= 3) {
        now.a[idx] -= 3;
        tmp=dfs(step+1,now);
        if (tmp!=-1) (res+=tmp)%=MOD;
        now.a[idx] +=3;
    }
    if (now.a[idx] >= 1 && now.a[step] >= 1) {
        now.a[idx] -= 1;   now.a[step] -= 1;
        tmp=dfs(step+1,now);
        if (tmp!=-1) (res+=tmp)%=MOD;
        now.a[idx] += 1;   now.a[step] += 1;
    }
    if (now.a[step] >= 3) {
        now.a[step] -= 3;
        tmp=dfs(step+1,now);
        if (tmp!=-1) (res+=tmp)%=MOD;
        now.a[step] += 3;
    }
    res=res?res:-1;
    if (step == idx+1) Map[now.hash()]=res;
    return res;
}
int main()
{
    #ifndef ONLINE_JUDGE
    freopen("3139.in","r",stdin);
    freopen("3139.out","w",stdout);
    #endif
    scanf("%d",&n);
    if (n==1) {puts("1");return 0;}
    for (int i=1;i<=n;++i) scanf("%d",start.a+i);
    start.a[0]=n;
    start.sort();
    bound.a[0]=1; bound.a[n]=0; Map[bound.hash()]=1;
    printf("%lld\n",dfs(2,start));
}

代码(………………将就着用吧,两种代码高亮的混合使用…………)

相关文章:

  • 2022-02-10
  • 2021-09-11
  • 2021-09-11
  • 2021-07-17
  • 2021-06-22
  • 2022-03-08
  • 2021-12-07
猜你喜欢
  • 2021-06-24
  • 2021-05-23
  • 2021-12-01
  • 2021-09-18
  • 2022-12-23
  • 2021-07-16
相关资源
相似解决方案