#动态规划,组合计数,树状数组,前缀和#F 简单计数题&K 最简单的题
先膜两位出题人
F 简单计数题
题目
有\(n\)个活动,预约期有\(k\)天,第\(j\)天YC可以获得\(a_j(1\leq a_j\leq n)\)张预约券,
他会在\(n\)个活动中等概率选择\(a_k\)个活动消耗预约券,
\(k\)天后,YC同时参加\(n\)个活动的信心就提高了\(\prod_{i=1}^nw_i\),\(w_i\)表示第\(i\)个活动消耗的预约券个数
问他能同时参加\(n\)个活动的信心的期望是多少,为了方便统计,答案乘上\(\prod_{i=1}^nC(n,a_i)\)并对\(10^9+7\)取模
分析
首先乘上最后那一坨就是将期望转换成了贡献和,因为那一坨就是方案数。
接着,贡献就是从\(w_{1\sim n}\)中各抽取1个的方案(乘法原理)
考虑拎出\(n\)个出来,如果有一种方案第\(j\)天的预约券中选择了\(p_j\)张,且\(n=\sum_{i=1}^kp_i\)
那么这种方案的贡献就是\(\prod_{i=1}^kC(n-p_i,a_i-p_i)\),
因为已经保证抽出来了,那么剩下的预约券可以随便分配
那么就可以列\(dp\)方程,设\(dp[i][j]\)表示前\(i\)天预约券共拎出\(j\)张的贡献,那么
\]
其中\(dp[0][0]=1\)
代码
#include <cstdio>
#include <cctype>
#define rr register
using namespace std;
const int mod=1000000007,N=1011;
int dp[21][N],c[N][N],n,k,a[N];
inline signed iut(){
rr int ans=0; rr char c=getchar();
while (!isdigit(c)) c=getchar();
while (isdigit(c)) ans=(ans<<3)+(ans<<1)+(c^48),c=getchar();
return ans;
}
inline signed mo(int x,int y){return x+y>=mod?x+y-mod:x+y;}
signed main(){
n=iut(),k=iut(),c[0][0]=dp[0][0]=1;
for (rr int i=1;i<=n;++i){
c[i][0]=c[i][i]=1;
for (rr int j=1;j<i;++j)
c[i][j]=mo(c[i-1][j-1],c[i-1][j]);
}
for (rr int i=1;i<=k;++i) a[i]=iut();
for (rr int i=1;i<=k;++i)
for (rr int j=0;j<=n;++j) if (dp[i-1][j])
for (rr int p=0;p<=n;++p){
if (j+p>n||p>a[i]) break;
rr int t=1ll*c[j+p][p]*c[n-p][a[i]-p]%mod;
dp[i][j+p]=mo(dp[i][j+p],1ll*t*dp[i-1][j]%mod);
}
return !printf("%d",dp[k][n]);
}
K 最简单的题
题目
给出两个长度为\(n\)的数列\(a,b\),
设\(f(i,j)=LIS(a_i,b_i,a_j,b_j)\),
问\(f(i,j)=1\sim 4\)的个数
\(1\leq n\leq 10^5,1\leq a,b\leq m\leq 10^3\)
分析
枚举\(j\),然后分类讨论,标绿为所在位置





首先一共5种情况,考虑它们的共同规律,当\(a_j<b_j\)时,右边罕见的出现平的分界线
其它情况都是要将纵轴顺时针旋转45度,实际上是逆时针。
被BPM大爷嘲讽后恶补高中数学,学完后却发现我在想桃子
还不如直接说原\((x,y)\)对应\((x-y,y)\),当然要平移横坐标,加上\(m\)
如下图\(m=15\)的情况

讲到这里好像还真是一道简单题
一开始我想的是用树状数组维护,但是BPM连\(STL::sort\)也没放过,
多组数据直接TLE(幸好O2卡过去了)
然后BPM就让我用前缀和做,其实思路差不多,
这里也不细讲了,反正代码很清晰
树状数组代码
#include <cstdio>
#include <cctype>
#include <cstring>
#include <algorithm>
#define rr register
using namespace std;
const int N=100011;
int n,m,Cnt,c[N]; long long dp[5];
struct rec{int x,y;}a[N],b[N<<1];
inline signed iut(){
rr int ans=0; rr char c=getchar();
while (!isdigit(c)) c=getchar();
while (isdigit(c)) ans=(ans<<3)+(ans<<1)+(c^48),c=getchar();
return ans;
}
bool cmp1(rec a,rec b){return a.y>b.y;}
inline signed query(int x){rr int ans=0; for (;x;x-=-x&x) ans+=c[x]; return ans;}
inline void update(int x,int y){for (;x<=m;x+=-x&x) c[x]+=y;}
signed main(){
while (scanf("%d%d",&n,&m)==2){
dp[1]=dp[2]=dp[3]=dp[4]=0;
for (rr int i=1;i<=n;++i) a[i]=(rec){iut(),iut()};
for (rr int i=1;i<=n;++i) if (a[i].x<a[i].y)
b[++Cnt]=(rec){a[i].x,a[i].y-(a[i].x+1==a[i].y)};
sort(b+1,b+1+Cnt,cmp1),sort(a+1,a+1+n,cmp1);
for (rr int i=1,j=1;i<=Cnt;++i){
while (j<=n&&a[j].y>=b[i].y) update(a[j].x,1),++j;
rr int t=query(b[i].x-1); dp[3]+=t,dp[2]+=j-t-1;
}
Cnt=0,memset(c,0,sizeof(c));
for (rr int i=1;i<=n;++i) b[i]=(rec){a[i].x>=a[i].y,a[i].x}; Cnt=n;
for (rr int i=1;i<=n;++i) if (a[i].x<a[i].y) b[++Cnt]=(rec){2,a[i].y-(a[i].x+1==a[i].y)};
sort(b+1,b+1+Cnt,cmp1); for (rr int i=1;i<=n;++i) a[i].x-=a[i].y-m;
for (rr int i=1,j=1,t=0;i<=Cnt;++i){
while (j<=n&&a[j].y>=b[i].y) t+=a[j].x<m,++j;
rr int t2=(b[i].x==2)?-1:1,t1=b[i].x!=1;
dp[2+t1]+=t*t2,dp[1+t1]+=(j-t-1)*t2;
}
reverse(a+1,a+1+n),Cnt=0,memset(c,0,sizeof(c));
for (rr int i=1;i<=n;++i) b[i].y=a[i].x-m+a[i].y;
for (rr int i=1;i<=n;++i) b[i].x=a[i].x<m;
sort(b+1,b+1+n,cmp1),reverse(b+1,b+1+n);
for (rr int i=1,j=1,t=0;i<=n;++i){
while (j<=n&&a[j].y<b[i].y) t+=a[j].x<m,++j;
dp[3+b[i].x]+=t,dp[2+b[i].x]+=j-t-1;
}
printf("%lld %lld %lld %lld\n",dp[1],dp[2],dp[3],dp[4]);
memset(c,0,sizeof(c));
}
return 0;
}
前缀和代码
#include <cstdio>
#include <cctype>
#include <cstring>
#define rr register
using namespace std;
const int N=100011,M=1011;
int n,m,Cnt,K,s[M<<1][M],x[N],y[N];
inline signed iut(){
rr int ans=0; rr char c=getchar();
while (!isdigit(c)) c=getchar();
while (isdigit(c)) ans=(ans<<3)+(ans<<1)+(c^48),c=getchar();
return ans;
}
signed main(){
while (scanf("%d%d",&n,&m)==2){
rr long long dp[5]={0,0,0,0,0};
memset(s,0,sizeof(s)),K=m<<1;
for (rr int i=1;i<=n;++i)
x[i]=iut(),y[i]=iut(),++s[x[i]][y[i]];
for (rr int i=1;i<=m;++i)
for (rr int j=1;j<=m;++j)
s[i][j]+=s[i-1][j]+s[i][j-1]-s[i-1][j-1];
for (rr int i=1;i<=n;++i)
if (x[i]<y[i]){
rr int px=x[i],py=y[i]-(x[i]+1==y[i]);
dp[3]+=s[px-1][m]-s[px-1][py-1];
dp[2]+=s[m][m]-s[px-1][m]-s[m][py-1]+s[px-1][py-1];
}
for (rr int i=1;i<=m;++i)
for (rr int j=1;j<=m;++j) s[i][j]=0;
for (rr int i=1;i<=n;++i) x[i]-=y[i]-m,++s[x[i]][y[i]];
for (rr int i=1;i<=K;++i)
for (rr int j=1;j<=m;++j)
s[i][j]+=s[i-1][j]+s[i][j-1]-s[i-1][j-1];
for (rr int i=1;i<=n;++i){
rr int T=x[i]<m,F=x[i]+y[i]-m,G=y[i]-(F+1==y[i]);
rr int TEMP=s[K][m]-s[m-1][m]-s[K][F-1]+s[m-1][F-1];
dp[3+T]+=s[m-1][F-1],dp[1+T]+=TEMP;
dp[2+T]+=s[K][m]-TEMP-s[m-1][F-1];
if (!T) continue;
dp[2]-=s[K][m]-s[m-1][m]-s[K][G-1]+s[m-1][G-1];
dp[3]-=s[m-1][m]-s[m-1][G-1];
}
printf("%lld %lld %lld %lld\n",dp[1],dp[2],dp[3],dp[4]);
}
return 0;
}
吐槽和膜拜时间
两位出题人出的题都是码题难度不高,思维难度不低的题目
其中K题所花的改题时间更多了那么一两个月233
吐槽树状数组开了O2比前缀和不开O2还要慢
主要聊一聊K题,历程大概是这样的
两个月,什么也不会,干聊纯属浪费时间;
一个月,学习高中数学;一个月,改完K题
其中大概只有一个月时间是没有被浪费掉的
其实我一开始觉得题目超级难,主要是想起了不堪回首的记忆
但其实说难不难,BPM没有一味地去帮助我,而是让我自己去思考,
虽然有点不情愿,但是我觉得很有道理,
想起考完\(CSP-S\)之后\(WYC\)也给我提出了一些建议
好吧,不管怎么说一模加油,不要丢脸
upd:20200410
#动态规划,组合计数,树状数组,前缀和#F 简单计数题&K 最简单的题的更多相关文章
- Codeforces Round #365 (Div. 2) D. Mishka and Interesting sum (离线树状数组+前缀xor)
题目链接:http://codeforces.com/contest/703/problem/D 给你n个数,m次查询,每次查询问你l到r之间出现偶数次的数字xor和是多少. 我们可以先预处理前缀和X ...
- HDU 6348 序列计数 (树状数组 + DP)
序列计数 Time Limit: 4500/4000 MS (Java/Others) Memory Limit: 262144/262144 K (Java/Others)Total Subm ...
- 51nod 1081 子段求和(线段树 | 树状数组 | 前缀和)
题目链接:子段求和 题意:n个数字序列,m次询问,每次询问从第p个开始L长度序列的子段和为多少. 题解:线段树区间求和 | 树状数组区间求和 线段树: #include <cstdio> ...
- FZU2013 A short problem —— 线段树/树状数组 + 前缀和
题目链接:https://vjudge.net/problem/FZU-2013 Problem 2013 A short problem Accept: 356 Submit: 1083Ti ...
- MooFest 树状数组 + 前缀和
比较友好的数据结构题 建议读者好好思考思考--. 可以分析出与前缀和的关系, 之后就愉快的套起树状数组辣 #include <cstdio> #include<queue> # ...
- ACM学习历程—HDU5700 区间交(树状数组 && 前缀和 && 排序)
http://acm.hdu.edu.cn/showproblem.php?pid=5700 这是这次百度之星初赛2B的第五题.省赛回来看了一下,有这样一个思路:对于所有的区间排序,按左值排序. 然后 ...
- CSU - 1551 Longest Increasing Subsequence Again —— 线段树/树状数组 + 前缀和&后缀和
题目链接:http://acm.csu.edu.cn/csuoj/problemset/problem?pid=1551 题意: 给出一段序列, 删除其中一段连续的子序列(或者不删), 使得剩下的序列 ...
- [USACO17JAN] Promotion Counting晋升者计数 (树状数组+dfs)
题目大意:给你一棵树,求以某节点为根的子树中,权值大于该节点权值的节点数 本题考查dfs的性质 离散+树状数组求逆序对 先离散 我们发现,求逆序对时,某节点的兄弟节点会干扰答案 所以,我们在递推时统计 ...
- 算法进阶 (LIS变形) 固定长度截取求最长不下降子序列【动态规划】【树状数组】
先学习下LIS最长上升子序列 看了大佬的文章OTZ:最长上升子序列 (LIS) 详解+例题模板 (全),其中包含普通O(n)算法*和以LIS长度及末尾元素成立数组的普通O(nlogn)算法,当然还 ...
- BZOJ 3787 Gty的文艺妹子序列(分块+树状数组+前缀和)
题意 给出n个数,要求支持单点修改和区间逆序对,强制在线. n,m<=50000 题解 和不带修改差不多,预处理出smaller[i][j]代表前i块小于j的数的数量,但不能用f[i][j]代表 ...
随机推荐
- [BUUCTF][Web][极客大挑战 2019]LoveSQL 1
打开靶机url,页面显示有两个输入框,框中输入123',发现两个框都有sql注入问题 爆出一下错误 You have an error in your SQL syntax; check the ma ...
- java轻量级规则引擎easy-rules使用介绍
我们在写业务代码经常遇到需要一大堆if/else,会导致代码可读性大大降低,有没有一种方法可以避免代码中出现大量的判断语句呢? 答案是用规则引擎,但是传统的规则引擎都比较重,比如开源的Drools,不 ...
- 麒麟系统开发笔记(五):制作安装麒麟系统的启动U盘、物理机安装麒麟系统以及搭建Qt开发环境
前言 电脑从U盘装麒麟系统,搭建实机Qt开发运行环境. 制作麒麟系统U盘(使用LiveUSB) 步骤一:先准备个至少8GB的U盘 之前购买的一批联想U盘,如下图: 查看U盘: 步 ...
- djang中文件上传MEDIA路径配置
1.settings.py文件中配置 # 项目中存储上传文件的根目录[暂时配置],注意,uploads目录需要手动创建否则上传文件时报错 MEDIA_ROOT = os.path.join(BASE_ ...
- 05、etcd 读请求执行流程
本篇内容主要来源于自己学习的视频,如有侵权,请联系删除,谢谢. 1.etcd读请求概览 etcd是典型的读多写少存储,在我们实际业务场景中,读一般占据2/3以上的请求.一个读 请求从client通过R ...
- 第121篇: DOM常用类型(Document、Element)
好家伙,本篇为<JS高级程序设计>第十四章"DOM编程"学习笔记 1.Document类型 Document 类型是 JavaScript 中表示文档节点的类型. ...
- curl比较有用的参数
精选参数: --include // -i curl的输出中包含http头信息--verbose // 比-i更加丰富,>表示请求的信息, <表示curl接收的信息 *表示curl额外提 ...
- Asp .Net Core 系列:Asp .Net Core 集成 Newtonsoft.Json
简介 Newtonsoft.Json是一个在.NET环境下开源的JSON格式序列化和反序列化的类库.它可以将.NET对象转换为JSON格式的字符串,也可以将JSON格式的字符串转换为.NET对象.这个 ...
- ChCore—实验 3:进程与线程、异常处理 部分记录
思考题 1: 内核从完成必要的初始化到用户态程序的过程是怎么样的?尝试描述一下调用关系. 内核启动到用户程序启动的流程: main ├── uart_init ├── mm_init ├── arch ...
- uniapp踩坑记录
sessionStorage.setItem('token', data.msg)uni.setStorage('token', res.data); 搞了半天登录后直接通过获取getstorage获 ...