zoukankan      html  css  js  c++  java
  • [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             B    3  -  0  3 
     C        3  0  -  3            C    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
    输出样例#1:
    3

    说明

    20%的数据满足N≤4;

    40%的数据满足N≤6;

    60%的数据满足N≤8;

    100%的数据满足3≤N≤10且至少存在一组解。

    转载自ljh2000http://www.cnblogs.com/ljh2000-jump/

    考虑直接爆搜的话,就是枚举当前的与之后的每一个比赛的结果是什么,但是复杂度很高。

    优化的话,考虑我枚举完一个的得分之后,剩下的状态打乱顺序不会影响最终结果,因为前面的贡献已经计算完毕了。

    那么我每次从小到大排序,并且把状态压起来,记忆化一下,就可以通过官方数据了,还有诸如鸡兔同笼和得分上限的剪枝也可以加。

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<algorithm>
     5 #include<map>
     6 using namespace std;
     7 typedef long long ll;
     8 int Mod=1000000007;
     9 map<ll,int>mp[12];
    10 map<ll,bool>use[12];
    11 int ans,a[12];
    12 int n;
    13 ll gethash(int *b)
    14 {int i;
    15   ll tot=0;
    16   for (i=1;i<=n;i++)
    17     tot=tot*29+b[i];
    18   return tot;
    19 }
    20 int dfs(int l,int r)
    21 {int i;
    22   if (a[l]>3*(r-l)) return 0;
    23   if (l>=r)
    24     {
    25       if (a[l]) return 0;
    26       if (l==n) return 1;
    27       int b[12];
    28       for (i=1;i<=n;i++)
    29     b[i]=a[i];
    30       sort(b+1,b+n+1);
    31       ll h=gethash(b);
    32       if (use[l+1][h]) return mp[l+1][h];
    33       else mp[l+1][h]=dfs(l+1,n);
    34       use[l+1][h]=1;
    35       return mp[l+1][h];
    36     }
    37   ll tot=0;
    38   if (a[l]>=3)
    39     {
    40       a[l]-=3;
    41       tot+=dfs(l,r-1);
    42       tot%=Mod;
    43       a[l]+=3;
    44     }
    45   if (a[l]&&a[r])
    46     {
    47       a[l]--;a[r]--;
    48       tot+=dfs(l,r-1);
    49       tot%=Mod;
    50       a[l]++;a[r]++;
    51     }
    52   if (a[r]>=3)
    53     {
    54       a[r]-=3;
    55       tot+=dfs(l,r-1);
    56       tot%=Mod;
    57       a[r]+=3;
    58      }
    59   return tot;
    60 }
    61 int main()
    62 {int i;
    63   cin>>n;
    64   for (i=1;i<=n;i++)
    65     scanf("%d",&a[i]);
    66   sort(a+1,a+n+1);
    67   ans=dfs(1,n);
    68   printf("%d",ans%Mod);
    69 }
  • 相关阅读:
    SA(后缀数组)专题总结
    LCT总结
    多项式全家桶
    fft.ntt,生成函数,各种数和各种反演
    P3939 数颜色
    P1879 [USACO06NOV]玉米田Corn Fields
    主席树模板
    P2633 Count on a tree
    P1972 [SDOI2009]HH的项链
    数论
  • 原文地址:https://www.cnblogs.com/Y-E-T-I/p/7652113.html
Copyright © 2011-2022 走看看