[BestCoder Round#26] Apple 【组合数学】
题目链接: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 【组合数学】的更多相关文章
- hdu4908 & BestCoder Round #3 BestCoder Sequence(组合数学)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4908 BestCoder Sequence Time Limit: 2000/1000 MS (Jav ...
- BestCoder Round #14
Harry And Physical Teacher Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Ja ...
- hdu5635 BestCoder Round #74 (div.2)
LCP Array Accepts: 131 Submissions: 1352 Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 13 ...
- BestCoder Round #81 (div.2) 1004 String(动态规划)
题目链接:BestCoder Round #81 (div.2) 1003 String 题意 中文题,上有链接.就不贴了. 思路 枚举起点i,计算能够达到k个不同字母的最小下标j,则此时有子串len ...
- [BestCoder Round #3] hdu 4908 BestCoder Sequence (计数)
BestCoder Sequence Problem Description Mr Potato is a coder. Mr Potato is the BestCoder. One night, ...
- BestCoder Round #89 02单调队列优化dp
1.BestCoder Round #89 2.总结:4个题,只能做A.B,全都靠hack上分.. 01 HDU 5944 水 1.题意:一个字符串,求有多少组字符y,r,x的下标能组成等比数列 ...
- BestCoder Round #90 //div all 大混战 一题滚粗 阶梯博弈,树状数组,高斯消元
BestCoder Round #90 本次至少暴露出三个知识点爆炸.... A. zz题 按题意copy Init函数 然后统计就ok B. 博弈 题 不懂 推了半天的SG..... 结果这 ...
- bestcoder Round #7 前三题题解
BestCoder Round #7 Start Time : 2014-08-31 19:00:00 End Time : 2014-08-31 21:00:00Contest Type : ...
- 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 ...
随机推荐
- python 多级菜单 纯循环与分支
源代码: dic1 = {'湖南':{'衡阳':{'珠晖区':'湖南工学院'},'湘潭':{'晖晖':'啦啦'}}, '北京':{'朝阳': {"德玛:北京大学"}}}print( ...
- poj 3294 Life Forms(后缀数组)
题意:给你最多100个字符串,求最长的且是一半以上的字符串的公共子串,如果有多个,按字典序输出. 思路:先把各个串拼起来,中间加上一个之前未出现过的字符,然后求后缀.然后根据h数组和sa数组,求出最长 ...
- VirtualBox 运行失败
运行 VirtualBox --help 安装 VirtualBox 后 运行 报错内核没加载问题 需要设置环境变量 内核加载的环境变量 export KERN_DIR=/usr/src/kernel ...
- RSA算法详解及C语言实现
RSA算法它是第一个既能用于数据加密也能用于数字签名的算法.它易于理解和操作,也很流行.算法的名字以发明者的名字命名:Ron Rivest, Adi Shamir 和Leonard Adleman.但 ...
- TOJ 2732存钱计划(三)(单源最短路)
存钱计划(三) 时间限制(普通/Java):1000MS/30000MS 运行内存限制:65536KByte 总提交: 18 测试通过: 16 描述 TZC的店铺比较 ...
- JSP-标准动作标记
JSP标准动作标记 在客户请求JSP页面时,JSP动作利用XML语法格式的标记来控制Servlet引擎的行为.利用JSP动作可以动态地插入文件.重用JavaBean组件.把用户重定向到另外的页面.为J ...
- 内存泄漏在 WPF 和 Silverlight 提防
瑞奇韭菜礼物 ︰ 内存泄漏在 WPF 和 Silverlight 提防 内存泄漏在 WPF 和 Silverlight 提防 WPF 和 Silverlight 允许您定义您的用户界面,用最少的代码将 ...
- 转载[POJ题型分类]
北大ACM题分类 主流算法: 1.搜索 //回溯 2.DP(动态规划) 3.贪心 4.图论 //Dijkstra.最小生成树.网络流 5.数论 //解模线性方程 6.计算几何 //凸壳.同等安置矩形的 ...
- Tomcat下work文件夹的作用
1.打补丁,重启tomcat时要删除work文件夹,有缓存. 2.work目录只是tomcat的工作目录,也就是tomcat把jsp转换为class文件的工作目录 jsp,tomcat的工作原理: 当 ...
- (whh仅供自己参考)进行ip网络请求的步骤
这个过程大致是这个样子: 1 添加通知 2 发送网络请求 里边有一个发送通知的操作 3 执行发送通知的具体操作 代码如下: 1 在VC添加通知 [[NSNotificationCenter defau ...