一道组合数问题--出自 曹钦翔_wc2012组合计数与动态规划

【问题描述】

众所周知,xyc 是一个宇宙大犇,他最近在给他的学弟学妹们出模拟赛。

由于 xyc 实在是太巨了,他出了一套自认为很水的毒瘤模拟赛(看看这题的文件名你就

知道是什么难度了)。

这些题目对于选手来说实在是太 hard 了,愤怒的选手们在评测的时候蜂拥而上,把 xyc

抬了起来……在这一过程中,xyc 用于评测的电脑也被选手们给砸坏了。

尽管选手们的成绩极其惨淡,xyc 还是想研究一下选手们的分数分布情况,他尝试还原

出了电脑中的部分信息:

已知有 n 人参加这场模拟赛,共有 m 道题。现在模拟赛己经结束,评测正在进行中,

对于已经结束评测的试题,已知每名选手这道题的答案是否正确,对于未结束评测的试题,

只知道每名选手是否提交了代码。每个题分数固定,提交正解的选手可以得到这一题的分数

(由于比赛太毒瘤了,每一题没有任何部分分),分数越高排名越靠前,分数相同编号小的

选手排名靠前。

xyc 想知道如果要在排名最靠前的 s 人中选出 t 人,有多少种组合的可能。

xyc 认为这个问题太 naive 了,所以他就把这个问题丢给你了。

【输入格式】

输入文件第一行是 m,接下去 m 行每行一个整数来表示每道题目的分值(整数是正的

表示该题已经评测,否则表示该题尚未评测,该题目的分值为这个整数的绝对值)

然后是一个整数 n,接下去是一个 n 行 m 列的字母阵,字母阵只包含 YN 两种字母(Yes

or No)。如果第 i 题已经完成评测,那么这个字母矩阵中第 j 行第 i 列的字母表示第 j 名选

手的第 i 题是否已经得分;如果第 i 题尚未完成评测,那么这个字母矩阵中第 j 行第 i 列的

字母表示第 j 名选手的第 i 题是否提交了代码。

最后两行两个数字,分别为 s 和 t。

如果先选出s个再选出其中t个,可以写爆搜,需要判重比较难写。

不如直接枚举我们选哪t个。

那么就需要分析一波了。

我们需要维护每位选手可以得到分数的最大值和最小值。

这样就可以得出他们分数的大小关系。

先把选手按照第一关键字为最大分数第二关键字为编号的方式排序。

那么就可以得到一些东西,比如说:

​ 对于一个选手i,我们设他是t名里的最后一名,那么他的前面一共有i-1个人,这i-1个人中有t-1个在t名中(这是非常显然的)。

​ 那么我们对于每一个i,就可以去枚举他前面这i-1个人中哪t-1个人在t名中就可以了。

​ 怎么枚举,还有一个需要注意的地方。

​ 就是可能在1到i-1中可能有一些人满足:如果i在前t名,那么这些人必然在前t名。

​ 为什么?其实非常简单:因为这些人的最小分数可能大于i的最大分数。

那么我们就需要计算出究竟有多少个这样的人,这也是我们按照最大分数排序的原因,这样我们就可以将这些人弄在一起。

​ 具体如下图:

那么我们就成功地把1到i这一段线段分成了两段。

​ 这样之后我们就可以毫无顾虑的开始做数学了。

​ 我们要从这两段中一共选择t个人(第i个人必选)

​ 那么枚举一个量j设为在第一段中也就是前p[i]个人中有j个人被选中,那么就会有t-j-1个人在第二段也就是后\(i-1-p[i]\)被选中。

​ 直接组合数?

​ 并不,因为j还要有一些范围。

​ 1,\(j<=p[i]\)显然吧

​ 2,\(j<=t-1\)第i个人必选

​ 3,\(j>=p[i]+t-s\),因为\(p[i]-j\)是第一段中不被选的,\(s-t\)是总共不会选的,那么就有:\(p[i]-j<=s-t\)

​ 4,\(p[i]+1<=s\)这样i才会在前s名中。

这样确定了j的范围之后,枚举j就可以了。

​ 即

\[ans=\prod_{j=max(0,p[i]+t-s)}^{max(p[i],t-1)}C(p[i],j)*C(i-p[i]-1,t-j-1)
\]

另外,求组合数不能用阶乘,用O(N)递推。

​ 即

\[C(n,i+1)=C(n,i)*(n-i)/(i+1)
\]

既然都会了,那就可以愉快地打代码了。

code:

#include <iostream>
#include <cstdio>
#include <algorithm> using namespace std; #define int long long const int wx=117; inline int read(){
int sum=0,f=1; char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1; ch=getchar();}
while(ch>='0'&&ch<='9'){sum=(sum<<1)+(sum<<3)+ch-'0'; ch=getchar();}
return sum*f;
} struct node{
int pts1,pts2; int flag,id;
friend bool operator < (const node & a,const node & b){
if(a.pts1==b.pts1)return a.id<b.id;
return a.pts1>b.pts1;
}
}a[wx],b[wx]; int n,m,T,S,ans;
int vis[wx],flag[wx],t[wx],tt[wx],p[wx];
char c[wx]; int Abs(int x){
if(x<0)return -x;
return x;
} int C(int nn,int mm){
if(nn<0||mm<0)return 0;
if(mm==0)return 1;
if(nn==0)return 0;
if(nn==mm)return 1;
if(mm>nn)return 0;
int re=1;
for(int i=0;i<nn-mm;i++){
re=re*(nn-i)/(i+1);
}
return re;
} signed main(){
freopen("ctsc.in","r",stdin);
freopen("ctsc.out","w",stdout); n=read();
for(int i=1;i<=n;i++){
int x=read();
if(x>0)flag[i]=1;
t[i]=Abs(x);
}
m=read();
for(int i=1;i<=m;i++){
scanf("%s",c+1);
a[i].id=i;
for(int j=1;j<=n;j++){
if(flag[j])
{
if(c[j]=='Y')a[i].pts1+=t[j],a[i].pts2+=t[j];
}
else
{
if(c[j]=='Y')a[i].pts1+=t[j];
}
}
}
S=read(); T=read();
sort(a+1,a+1+m);
for(int i=1;i<=m;i++){
for(int j=1;j<i;j++){
p[i]+=((a[j].pts2>a[i].pts1)||(a[j].pts2==a[i].pts1&&a[j].id<a[i].id));
}
}
for(int i=T;i<=m;i++){
if(p[i]>S)break;
int don=max(p[i]-S+T,(long long)0);
int upp=min(p[i],T-1);
for(int j=don;j<=upp;j++){
ans+=C(p[i],j)*C(i-p[i]-1,T-j-1);
}
} printf("%lld\n",ans);
return 0;
}

一道组合数问题--出自 曹钦翔_wc2012组合计数与动态规划的更多相关文章

  1. [转] ACM中国国家集训队论文集目录(1999-2009)

    国家集训队1999论文集 陈宏:<数据结构的选择与算法效率——从IOI98试题PICTURE谈起>来煜坤:<把握本质,灵活运用——动态规划的深入探讨>齐鑫:<搜索方法中的 ...

  2. NOI 国家集训队论文集

    鉴于大家都在找这些神牛的论文.我就转载了这篇论文合集 国家集训队论文分类 组合数学 计数与统计 2001 - 符文杰:<Pólya原理及其应用> 2003 - 许智磊:<浅谈补集转化 ...

  3. ACM/IOI 历年国家集训队论文集和论文算法分类整理

    国家集训队1999论文集 陈宏:<数据结构的选择与算法效率--从IOI98试题PICTURE谈起> 来煜坤:<把握本质,灵活运用--动态规划的深入探讨> 齐鑫:<搜索方法 ...

  4. ACM/IOI 国家队集训队论文集锦

    转自:https://blog.csdn.net/txl199106/article/details/49227067 国家集训队1999论文集 陈宏:<数据结构的选择与算法效率——从IOI98 ...

  5. hdu 2486/2580 / poj 3922 A simple stone game 博弈论

    思路: 这就是K倍动态减法游戏,可以参考曹钦翔从“k倍动态减法游戏”出发探究一类组合游戏问题的论文. 首先k=1的时候,必败态是2^i,因为我们把数二进制分解后,拿掉最后一个1,那么会导致对方永远也取 ...

  6. HDU 3404&POJ 3533 Nim积(二维&三维)

    (Nim积相关资料来自论文曹钦翔<从"k倍动态减法游戏"出发探究一类组合游戏问题>) 关于Nim积计算的两个函数流程: 代码实现如下: ][]={,,,}; int N ...

  7. bzoj千题计划252:bzoj1095: [ZJOI2007]Hide 捉迷藏

    http://www.lydsy.com/JudgeOnline/problem.php?id=1095 点分树+堆 请去看 http://www.cnblogs.com/TheRoadToTheGo ...

  8. 博弈论BOSS

    基础博弈的小结:http://blog.csdn.net/acm_cxlove/article/details/7854530 经典翻硬币游戏小结:http://blog.csdn.net/acm_c ...

  9. 【Mark】博弈类题目小结(HDU,POJ,ZOJ)

    转载请注明出处,谢谢http://blog.csdn.net/ACM_cxlove?viewmode=contents    by---cxlove 首先当然要献上一些非常好的学习资料: 基础博弈的小 ...

随机推荐

  1. 【290】Python 模块

    参考:Python 模块 目录: 1. import 语句(模块的引入) 2. from...import 语句 3. from...import * 语句 4. dir() 函数 5. Python ...

  2. deeplearning.ai 旁听如何做课后编程作业

    在上吴恩达老师的深度学习课程,在coursera上. 我觉得课程绝对值的49刀,但是确实没有额外的钱来上课.而且课程提供了旁听和助学金. 之前在coursera上算法和机器学习都是直接旁听的,这些课旁 ...

  3. 201671010140. 2016-2017-2 《Java程序设计》java学习第八周

    第八周Java学习      本周,老师带领我们完善了一下继承,借口,拷贝,lambda表达式,内部类方面欠缺,不完善的地方,帮助我们查漏补缺.       以拷贝的学习为例,我本来对拷贝的理解非常浅 ...

  4. Physics Material

    [Physics Material] 1. The Physics Material is used to adjust friction and bouncing effects of collid ...

  5. Vue基础以及指令, Vue组件

    Vue基础篇一 Vue指令 Vue的指令directive很像我们所说的自定义属性,指令时Vue模板中最常用的功能,它带有v-前缀,功能是当表达式改变的时候,相应的行为作用在DOM上. <div ...

  6. 有关Lucene的问题(4):影响Lucene对文档打分的四种方式

    原文出自:http://forfuture1978.iteye.com/blog/591804点击打开链接 在索引阶段设置Document Boost和Field Boost,存储在(.nrm)文件中 ...

  7. Codeforces 1109E 线段树

    思路及博客:https://www.cnblogs.com/uid001/p/10507346.html 代码: #include <bits/stdc++.h> #define LL l ...

  8. 利用arcgis实现经纬度和平面坐标互转

    一平面直角坐标(投影坐标)转经纬度 基本程序是这样的 经纬度计算操作 1. 定义坐标系:在AreToolbox下→数据管理工具→投影和变换→定义投影→输入数据或要素点击▼选择定义同层(同时在坐标系中点 ...

  9. Android不间断上报位置信息-应用进程防杀指南

    没用的 除非加入白名单 或者用户自己设置锁屏后不被杀死 不然的话 锁屏5分钟以内app会被杀死,包 括所有的service. 说白了就是定位不要纯依赖gps,很多硬件为了省电,会对熄屏下的模块功能和运 ...

  10. 编写高质量代码改善C#程序的157个建议——建议35:使用default为泛型类型变量指定初始值

    建议35:使用default为泛型类型变量指定初始值 有些算法,比如泛型集合List<T>的Find算法,所查找的对象可能会是值类型,也有可能是引用类型.在这种算法内部,我们常常会为这些值 ...