题目链接:HDOJ - 5160

题目分析

第一眼看上去,要求统计所有不同排列对答案的贡献。嗯...完全没有想法。

但是,如果我们对每个数字单独考虑,计算这个数字在总答案中的贡献,就容易多了。

对于一个数字 ai ,有 ni 个 。比它大的数字有 p 个,比它小的数字有 q 个。所有的数字一共有 N 个。

首先,比它小的数字对它不会造成影响,所以我们只要考虑它和比它大的数字。那么我们就在 N 个位置中,选 (ni + p) 个位置,给它和比它大的数字。

然后比它大的数字有 x1 种排列,比它小的数字有 x2 种排列。这个如何来求呢?这是多重集排列。

  多重集排列,对于一个多重集 A={a1*n1, a2*n2, a3*n3, ak*nk} 。排列数为 Sum(n1...nk)!/(n1!n2!n3!...nk!)

那么 ai 有多少个会被记入答案呢?我们枚举每种情况:有 ni 个记入答案, (ni-1) 个, (ni-2)个 .... 1 个。

如果有 k 个 ai 无法记入答案,说明有比它们大的数在他们前面,也就是说他们被插到了 p 个比他们大的数后面或之间。这 p 个数后面一共有 p 个位置,每个位置都可以插入任意个 ai ,这种情况数为 C(k + p - 1, k) (相当于向 p 个箱子里分配 k 个球,隔板法)。

那么 ai 对答案的贡献就为 C(N, ni + p) * x1 * x2 * sigma((ni - k) * C(k + p - 1, k)) (0 <= k < ni) * ai 。

Warning!

出现的错误: % 的优先级比 + 高!如果这样 Ans = Ans + temp % Mod 。Ans 是会爆掉的!!应该是 Ans = (Ans + Temp) % Mod 。

昨天晚上因为这个错误debug了3hours!!!!!!

代码

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm> using namespace std; const int MaxN = 100000 + 15; typedef long long LL; const LL Mod = 1000000007ll; int T, n, Top;
LL Ans;
LL A[MaxN], f[MaxN], g[MaxN], Sum[MaxN], NSum[MaxN], Fac[MaxN], NY_Fac[MaxN]; struct ES_Num
{
LL Cnt, Num;
ES_Num() {}
ES_Num(LL a, LL b) {
Num = a; Cnt = b;
}
} ES[MaxN]; LL Pow(LL a, LL b) {
LL f, ret;
f = a; ret = 1ll;
while (b) {
if (b & 1) {
ret *= f;
ret %= Mod;
}
b >>= 1;
f *= f;
f %= Mod;
}
return ret;
} void Init() {
int Max_Num = 100000 + 5;
Fac[0] = 1;
for (int i = 1; i <= Max_Num; ++i)
Fac[i] = Fac[i - 1] * i % Mod;
for (int i = 0; i <= Max_Num; ++i)
NY_Fac[i] = Pow(Fac[i], Mod - 2);
} LL C(LL a, LL b) {
if (b == 0) return 1;
if (a < b) return 0;
LL ret;
ret = Fac[a];
ret = ret * NY_Fac[a - b] % Mod;
ret = ret * NY_Fac[b] % Mod;
return ret;
} int main()
{
Init();
scanf("%d", &T);
for (int Case = 1; Case <= T; ++Case) {
scanf("%d", &n);
Ans = 0;
for (int i = 1; i <= n; ++i) scanf("%d", &A[i]);
sort(A + 1, A + n + 1);
Top = 0;
for (int i = 1; i <= n; ++i) {
if (i != 1 && A[i] == A[i - 1]) ++(ES[Top].Cnt);
else ES[++Top] = ES_Num((LL)A[i], 1);
}
Sum[0] = 0;
for (int i = 1; i <= Top; ++i)
Sum[i] = Sum[i - 1] + ES[i].Cnt;
NSum[Top + 1] = 0;
for (int i = Top; i >= 1; --i)
NSum[i] = NSum[i + 1] + ES[i].Cnt;
LL t = 1;
f[0] = 1;
for (int i = 1; i <= Top; ++i) {
t = t * Fac[Sum[i]] % Mod * NY_Fac[ES[i].Cnt] % Mod;
f[i] = t;
t = t * NY_Fac[Sum[i]] % Mod;
}
t = 1;
g[Top + 1] = 1;
for (int i = Top; i >= 1; --i) {
t = t * Fac[NSum[i]] % Mod * NY_Fac[ES[i].Cnt] % Mod;
g[i] = t;
t = t * NY_Fac[NSum[i]] % Mod;
}
LL x, y;
for (int i = 1; i <= Top; ++i) {
x = 0;
for (int j = 0; j < ES[i].Cnt; ++j) {
y = (ES[i].Cnt - j) * C(NSum[i + 1] + j - 1, j) % Mod;
x = (x + y) % Mod;
}
x = x * ES[i].Num % Mod;
x = x * f[i - 1] % Mod;
x = x * g[i + 1] % Mod;
x = x * C(NSum[1], NSum[i]) % Mod;
Ans = (Ans + x) % Mod;
}
printf("Case #%d: %d\n", Case, (int)Ans);
}
return 0;
}

  

[BestCoder Round#26] Apple 【组合数学】的更多相关文章

  1. hdu4908 &amp; BestCoder Round #3 BestCoder Sequence(组合数学)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4908 BestCoder Sequence Time Limit: 2000/1000 MS (Jav ...

  2. BestCoder Round #14

    Harry And Physical Teacher Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Ja ...

  3. hdu5635 BestCoder Round #74 (div.2)

    LCP Array  Accepts: 131  Submissions: 1352  Time Limit: 4000/2000 MS (Java/Others)  Memory Limit: 13 ...

  4. BestCoder Round #81 (div.2) 1004 String(动态规划)

    题目链接:BestCoder Round #81 (div.2) 1003 String 题意 中文题,上有链接.就不贴了. 思路 枚举起点i,计算能够达到k个不同字母的最小下标j,则此时有子串len ...

  5. [BestCoder Round #3] hdu 4908 BestCoder Sequence (计数)

    BestCoder Sequence Problem Description Mr Potato is a coder. Mr Potato is the BestCoder. One night, ...

  6. BestCoder Round #89 02单调队列优化dp

    1.BestCoder Round #89 2.总结:4个题,只能做A.B,全都靠hack上分.. 01  HDU 5944   水 1.题意:一个字符串,求有多少组字符y,r,x的下标能组成等比数列 ...

  7. BestCoder Round #90 //div all 大混战 一题滚粗 阶梯博弈,树状数组,高斯消元

    BestCoder Round #90 本次至少暴露出三个知识点爆炸.... A. zz题 按题意copy  Init函数 然后统计就ok B. 博弈 题  不懂  推了半天的SG.....  结果这 ...

  8. bestcoder Round #7 前三题题解

    BestCoder Round #7 Start Time : 2014-08-31 19:00:00    End Time : 2014-08-31 21:00:00Contest Type : ...

  9. Bestcoder round #65 && hdu 5593 ZYB's Tree 树形dp

    Time Limit: 3000/1500 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)Total Submissio ...

随机推荐

  1. (转)PHP连接数据库之PHP连接MYSQL数据库代码

    PHP连接数据库之PHP连接MYSQL数据库代码 < ?php $mysql_server_name='localhost'; //改成自己的mysql数据库服务器 $mysql_usernam ...

  2. WinForm中关于控件焦点的问题

    方法一: 在打开一个窗体时,我们往往需要设置焦点让光标出现在我们希望它出现的位置上. 这时我们可以在窗体的Activated事件中设置焦点 例如我们希望光标在打开窗体的时候出现在textBox1上,我 ...

  3. 基于NPOI开源框架写的ExcelHelper【转载】

    namespace ExcelTest { using System; using System.Collections.Generic; using System.Data; using Syste ...

  4. Windows 8和CentOS 6.4(64)双系统硬盘安装教程

    最近在笔记本上升级原来的系统Win7到Win8,同时又安装了CentOS 6.4(64)系统,实现双系统共存.着实折腾了一番,主要是CentOS6.4(64)的两个iso文件加起来5G多(其实只用第一 ...

  5. android MediaCodec 音频编解码的实现——转码

    原文地址:http://blog.csdn.net/tinsanmr/article/details/51049179 从今天开始 每周不定期更新博客,把这一周在工作与学习中遇到的问题做个总结.俗话说 ...

  6. js自定义方法名

    自定义方法名: <script language="javascript" type="text/javascript">window.onload ...

  7. 分离数据库(Detach database).

    Many times, we often needs to detach our databases if we want to copy it to another database instanc ...

  8. AFNETWORKING tabelView没有reloadData,报错unsupported URL

    Error Domain=NSURLErrorDomain Code=-1002 "unsupported URL" UserInfo=0x7f9dc278aa60 {NSUnde ...

  9. 334. Increasing Triplet Subsequence My Submissions Question--Avota

    问题描述: Given an unsorted array return whether an increasing subsequence of length 3 exists or not in ...

  10. Flume研究心得

    最近两天,仔细的看了一下Flume中央日志系统(版本号:1.3.X),Flume在本人看来,还是一个非常不错的日志收集系统的,其设计理念非常易用,简洁.并且是一个开源项目,基于Java语言开发,可以进 ...