USACO 2019 January Contest Platinum T3: Train Tracking 2

题目大意

每天特快列车都会经过农场。列车有N节车厢(1≤N≤10^5),每节车厢上有一个1到10^9之间的正整数编号;不同的车厢可能会有相同的编号。 平时,Bessie会观察驶过的列车,记录车厢的编号。但是今天雾实在太浓了,Bessie一个编号也看不见!幸运的是,她从城市里某个可靠的信息源获知了列车编号序列的所有滑动窗口中的最小值。具体地说,她得到了一个正整数K,以及N−K+1个正整数c1,…,cN+1−K,其中ci是车厢i,i+1,…,i+K−1之中编号的最小值。

帮助Bessie求出满足所有滑动窗口最小值的对每节车厢进行编号的方法数量。由于这个数字可能非常大,只要你求出这个数字对10^9+7取余的结果Bessie就满意了。

Bessie的消息是完全可靠的;也就是说,保证存在至少一种符合要求的编号方式。

题目分析

一上来似乎题目条件无从入手,所以我们首先考虑此题的一个弱化版本:如果所有 ci 都?相等时该怎么做。

现在假设有 len个数,取值从 v 到 1e9,而且每连续 k 个数至少有一个是 v 。

那么取值就只有 v 和 >v 两种取值了,>v 的取值有1e9−v 种,令 x=1e9 - v 。

那么有一个显然的dp,fi? 表示这个前i个数的答案

fi ?= (x+1) fi-1? − xk fi−k−1?

第 i 个数随便选,乘上前 i−1 个数的答案,这时可能出现问题,就是第 i−k+1个数到第i个数都 >v 导致了不合法,所以要减掉这些情况

为什么减掉的是xk fi−k−1?呢,显然这 k 个数的放法共 x种没有问题,要注意一下从第 i−k+1个数到第 i−1个数都 >v,

那么只有第 i−k 个数取值是 v 才能够满足最小值的条件,所以前面的取值方案数是  fi−k−1

考虑完这个后,我们就可以入手了。

令 f(v,len)表示 "有 len个数,取值从 v 到 1e9,而且每连续 k 个数至少有一个是 v" 这个问题的答案

首先,显然可以将一段相等的 ci 合并起来

对于一个段 ci=?=cj?,如果全部只有这一段,方案数为ss(ci?,j−i+k)

如果有一个 ci1> ci?

可得

min{ai1?,?,ai+k2?}=ci−1?

相当于 min{ai1?,?,ai+k2?} ≥ ci−1? 

又因为 min{ai?,?,ai+k1?}=ci?

前面已经推出 ai?,?,ai+k2? ≥ ci1? > ci?了,所以这些都不可能是最小值

所以对于 ci 这一段的最小值只能有一个就是  ai+k1?=ci?

前面的数也都在前一段的范围内计算过了

所以这一段相当于最前面 k 个数就没了,其中前 k−1个数会在前面段计算答案,第k个数只有一个取值 ci?

对于后面也同理,如果 cj+1?>c?则后面 k 个数也没了

所以一段的 len 实际上是 j−i+k 减去 0~2 个 k

对于所有的段依次求解最后方案数乘起来即可

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 typedef long long ll;
 4 const ll Mod=1e9+7;
 5 const int MAXN=1e5+10;
 6 int n,k;
 7 ll c[MAXN];
 8 ll f[MAXN];
 9
10 inline ll ksm(ll x,ll y){
11     ll res=1;
12     while(y){
13         if(y&1) res=res*x%Mod;
14         x=x*x%Mod;
15         y>>=1;
16     }
17     return res;
18 }
19
20 inline int Solve(ll v,ll len){
21     ll x=1e9-v,xp=ksm(x,k);
22     f[0]=f[1]=1;
23     for(int i=2;i<=len+1;++i){
24         f[i]=(x+1)*f[i-1]%Mod;
25         if(i-k-1>=0)
26             f[i]=(f[i]-xp*f[i-k-1]%Mod+Mod)%Mod;
27     }
28     return f[len+1];
29 }
30 int main(){
31     scanf("%d%d",&n,&k);
32     for(int i=1;i<=n-k+1;++i)
33         scanf("%lld",&c[i]);
34     ll ans=1,len;
35     for(int i=1,j;i<=n-k+1;i=j+1){
36         j=i;
37         while(c[j+1]==c[i]) ++j;
38         len=(ll)j-i+k;
39         if(i!=1&&c[i-1]>c[i]) len-=k;
40         if(j!=n-k+1&&c[j+1]>c[i]) len-=k;
41         if(len) ans=ans*Solve(c[i],len)%Mod;
42     }
43     printf("%lld",ans);
44     return 0;
45 }

原文地址:https://www.cnblogs.com/LI-dox/p/11223731.html

时间: 2024-10-07 08:49:09

USACO 2019 January Contest Platinum T3: Train Tracking 2的相关文章

USACO 2019 February Contest Platinum T1: Cow Dating

题目大意 由于目前可供奶牛们使用的约会网站并没有给Farmer John留下深刻印象,他决定推出一个基于新匹配算法的奶牛交友网站,该算法可基于公牛和母牛间的共同兴趣对公牛和母牛进行匹配. Bessie在寻找情人节Barn Dance的合作伙伴时,决定试用这个网站.在注册账户之后,FJ的算法为他给出了一个长度为 N(1≤N≤1e6) 的匹配列表,列表上每头公牛接受她舞蹈邀请的概率为 p (0 < p < 1). Bessie决定向列表中的一个连续区间内的奶牛发送邀请,但Bessie希望恰好只有一

USACO 2017 December Contest Platinum T3: Greedy Gift Takers

题目大意 有 N(1≤N≤1e5)头牛按顺序排成一列,编号从 1 到 N,1 号牛在队头,N 号牛在队尾. 每次位于队头的牛 i 拿到一个礼物,然后插入到从队尾数ci?头牛之前的位置..举个栗子: 初始队列 1,2,3,4,5 c1?= 2,c2? = 3,则第一次操作后的序列为 2,3,1,4,5,第二次操作后的序列为 3,2,1,4,5.重复无限次操作,求最后有几头牛拿不到礼物. 题目分析 一上来有个显然的结论,若一个人得不到礼物那么原序列中在他后面的人肯定也得不到礼物,因为后面的人跳不到前

USACO 2018 December Contest Platinum T2: Sort It Out

题目大意 FJ有 N(1≤N≤1e5 )头奶牛(分别用 1…N 编号)排成一行.FJ喜欢他的奶牛以升序排列,不幸的是现在她们的顺序被打乱了.在过去FJ曾经使用一些诸如“冒泡排序”的开创性的算法来使他的奶牛排好序,但今天他想偷个懒.取而代之,他会每次对着一头奶牛叫道“按顺序排好”.当一头奶牛被叫到的时候,她会确保自己在队伍中的顺序是正确的(从她的角度看来).当有一头紧接在她右边的奶牛的编号比她小,她们就交换位置.然后,当有一头紧接在她左边的奶牛的编号比她大,她们就交换位置.这样这头奶牛就完成了“按

USACO 2016 December Contest Gold T3: Lasers and Mirrors

题目大意 出于某种原因,农夫约翰的牛总是在举行激光表演. 对于他们的最新展会,奶牛已经购买了一个大功率的激光器 - 这么大,事实上,他们似乎不能轻易地从它交付的位置移动.他们想以某种方式将激光的光发送到FJ物业另一侧的谷仓.激光器和谷仓都可以被认为位于FJ农场的地图上的2D平面中的点上.牛计划指挥激光器,使得它发出水平或竖直(即,与x或y轴平行)的光束.他们会将这个光束从一些镜子反射回去,直接到谷仓. 在农场上有N个栅栏(1≤N≤100,000),位于不同的二维点(也不同于激光和谷仓),牛可以安

USACO 2017 December Contest Platinum T2: Push a Box

题目大意 一个谷仓是一个N*M的矩形网格,有一些网格里有干草.Bessie站在其中一个格子内,还有一个格子里有一个大木箱.Bessie不能和大木箱在一个格子里,也不能和干草在一个格子里. 如果她不与干草一个格子,她就可以往自己旁边的四个方向(东西南北)移动,如果她想移动到有木箱的格子里,那个木箱就会被她推一格(只要木箱的那个方向还有空间),如果没有空间,那Bessie就不能移动了. 给你谷仓的布局(空格子,干草以及木箱位置)以及Bessie的出发位置和箱子要被推到的位置,请你帮忙计算Bessie

6546. 【GDOI2020模拟4.8】USACO 2020 Open Contest, Platinum(circus)

题目描述 Farmer John 马戏团的 N 头奶牛( 1 ≤ N ≤ 10^5 )正在准备她们接下来的演出.演出在一棵结点编号为 1 - N 的树上进行.演出的"起始状态"可以定义为一个整数 1 ≤ K ≤ N 以及奶牛 1 - K 在树上的结点分布,使得没有两头奶牛位于相同的结点. 在一场演出中,奶牛们可以进行任意次数的"移动".在一次移动中,一头奶牛从她的当前所在结点移动到一个未被占据的相邻结点.称两个起始状态是等价的,如果一个状态可以通过一系列移动到达另一

【AtCoder】diverta 2019 Programming Contest

diverta 2019 Programming Contest 因为评测机的缘故--它unrated了.. A - Consecutive Integers #include <bits/stdc++.h> #define fi first #define se second #define pii pair<int,int> #define mp make_pair #define pb push_back #define space putchar(' ') #define

USACO 2017 January Platinum

因为之前忘做了,赶紧补上. T1.Promotion Counting 题目大意:给定一个以1为根的N个节点的树(N<=100,000),每个节点有一个权值,对于每个节点求出权值比它大的子孙的个数. 思路:肯定先要求出dfs序,首先无脑想到主席树,后来发现只要按权值从大到小处理就不用那么麻烦了. #include<cstdio> #include<algorithm> using namespace std; char B[1<<26],*S=B,C;int X;

USACO 2016 US Open Contest Gold T3: 248

题目大意 给定一个1*n(2≤N≤248)的地图,在里面玩2048,每次可以合并相邻两个(数值范围1-40),问最大能合出多少.注意合并后的数值并非加倍而是+1,例如2与2合并后的数值为3. 题目分析 观察数据范围与题目,n<=248 并且 “每次可以合并相邻两个” ,不难想到要使用区间DP. 令 f[i][j] 表示区间 i~j 合并的最大值,则显然,转移为 (i < k < j )若f[i][k]==f[k+1][j] 则 f[i][j]=max(f[i][k]+1,f[i][j])