T1 取球游戏

问题描述

现有\(N\)个小球,依次编号为\(1\)到\(N\),这些小球除了编号以外没有任何区别。从这\(N\)个小球中取出\(M\)个,请问有多少种取球方案使得在取出的\(M\)个小球中,编号最小的小球的编号为\(K\)。

考虑到方案数可能很大,请输出方案数对\(1e9+7\)去模的值。

输入格式

输入数据只有一行,包含三个整数\(N,M,K\)。

输出格式

一个整数,表示取法总数对\(1e9+7\)取模的值。

样例

样例输入1
4 2 2
样例输出1
2
样例输入2
888 222 555
样例输出2
424089030

题解

板子题,卢卡斯定理。这里给卢卡斯定理的板子写法。

#include<bits/stdc++.h>
#define p 1000000007
#define maxn 10000005
using namespace std;
long long E[maxn];
inline void init(){
E[0]=1;
for(register int i=1;i<maxn;i++)E[i]=E[i-1]*i%p;
}
inline long long inv(long long a,long long m){
if(a==1)return a;
return inv(m%a,m)*(m-m/a)%m;
}
inline long long lucas(long long n,long long m){
long long ans=1;
while(n&&m){
long long a=n%p;
long long b=m%p;
if(a<b)return 0;
ans=ans*E[a]%p*inv(E[a-b]*E[b]%p,p)%p;
n/=p;
m/=p;
}
return ans;
}
long long n,m,k;
int main(){
init();
cin>>n>>m>>k;
n-=k;m-=1;
printf("%lld",lucas(n,m));
return 0;
}

T2 维修机器人

问题描述

土豪贾老师拥有\(n\)个机器人。这\(n\)个机器人排成一行,第\(i\)个机器人的身高

为\(h_i\)。贾老师发现这些机器人的身高参差不齐,看起来十分不美观,于是决定对

它们的身高进行修改。

贾老师希望修改后的机器人队伍身高值单调,形式化地说,满足下面两个条

件之一的机器人队伍是合格的队伍 。

  • \(h_1\le h_2\le ... \le h_{n-1} \le h_n\)
  • $h_1 \ge h_2\ge...\ge h_{n-1} \ge h_n $

增加第\(i\)个机器人的身高,需要的费用为\(m_1\),减小第\(i\)个机器人的身高,需

要的费用为\(m_2\)。注意,费用与是否增加和是否减小有关,与具体增加或减小的

数值无关。对于一个身高为\(5\)的机器人,把它的身高增加到\(6\)和增加到\(100\)所需

要的费用都为\(m_1\)。

贾老师希望你能帮他计算出,为了得到合格的机器人队伍,所需要花费的最

小费用是多少。 由于某些特殊的原因, 我们保证这\(n\)个机器人不同的身高不会超

过\(1,000\)个。

输入格式

输入文件共包含两行。

第一行共包括三个正整数,分别为\(n,m_1,m_2\),含义如上文所述。

第二行包含\(n\)个整数,依次表示每个机器人的身高\(h_i\)。

输出格式

共一行,包含一个整数,表示贾老师所需修理费用的最小值。

样例

样例输入1
5 2 3
1 2 3 5 4
样例输出1
2
样例输入2
15 5 7
10 10 10 10 10 9 2 8 7 6 1000 5 3 4 1
样例输出2
17

数据规模与规定

题解

首先考\(m_1=m_2\)的情况,因为升高或降低一个机器人的高度所需要的花费一样,所以我们只需要设法用最小的步数将整个序列变为单调递增或单调递减即可。此时我们可以选择求整个序列的最长不上升与最长不下降序列子序列,用\([n-max(up_{size},down_{size})]*m_1\)即可得到答案

代码如下(75)

#include<bits/stdc++.h>
#define maxn 50005
#define inf 0x3f3f3f3f
using namespace std;
inline char get(){
static char buf[30],*p1=buf,*p2=buf;
return p1==p2 && (p2=(p1=buf)+fread(buf,1,30,stdin),p1==p2)?EOF:*p1++;
}
inline long long read(){
register char c=get();register long long f=1,_=0;
while(c>'9' || c<'0')f=(c=='-')?-1:1,c=get();
while(c<='9' && c>='0')_=(_<<3)+(_<<1)+(c^48),c=get();
return _*f;
}
bool cmp(long long a,long long b){
return a>b;
}//重载upper_bound
long long n,m1,m2;
long long a[maxn],f[maxn],g[maxn];
long long ans1,ans2;
long long cas[maxn];
int main(){
//freopen("robot.in","r",stdin);
//freopen("robot.out","w",stdout);
n=read();m1=read();m2=read();
for(register long long i=1;i<=n;i++)a[i]=read();
if(m1==m2){
for(register long long i=0;i<maxn;i++)f[i]=0,g[i]=0x3f3f3f3f;
g[0]=0;
for(register long long i=1;i<=n;i++){
f[i]=upper_bound(g+1,g+1+ans1,a[i])-g;
g[f[i]]=a[i];
ans1=max(ans1,f[i]);
}
//cout<<ans1<<endl;
for(register long long i=0;i<maxn;i++)f[i]=0,g[i]=0x3f3f3f3f;
g[0]=0;
for(register long long i=1;i<=n;i++){
f[i]=upper_bound(g+1,g+1+ans2,a[i],cmp)-g;
g[f[i]]=a[i];
ans2=max(ans2,f[i]);
}
//cout<<ans2<<endl;
printf("%lld",(n-max(ans1,ans2))*m1);
return 0;
}
return 0;
}

注意到题目的关键条件,不同的\(h_i\)取值不超过$T=1000 $个。考虑将

读入数据先离散成\(1——1000\)的整数,接下来用动态规划解决。设\(dp[i][j]\)表示将前 i 个机

器人改为单调不减,第\(i\)个机器人的身高变为\(j\)所需的最小费用。则\(dp[i][j]=min(dp[i-
1][k])+change(a[i],j)(1≤k≤j)\)。其中\(change(x,y)\)表示把一个机器人的身高从\(x\)改为\(y\)所需的

费用,这个值只能是\(m_1\)或者0或者\(m_2\) 。

按上述做法时间复杂度为\(O(nT^2 )。\)注意到对于当前的决策位置,\(k\)的可取值越来越

多, 因此可以再同时维护$ min(dp[i-1][k])$, 这样转移代价变成 \(O(1)\), 时间复杂度变为\(O(nT)\),

可以获得\(100\)分。

#include <bits/stdc++.h>
#define maxn 50005
#define maxt 1005
#define maxl 1000005
#define inf 0x3f3f3f3f
using namespace std;
int n,m1,m2;
int p[maxn];
int t[maxt];
bool vis[maxl];
int level[maxl];
int cnt;
int now,pre;
int minv;
int dp[2][maxt];
int ans=inf;
void init(){
scanf("%d %d %d",&n,&m1,&m2);
for (int i=1;i<=n;i++){
scanf("%d",&p[i]);
if (!vis[p[i]]) t[++cnt]=p[i];
vis[p[i]]=true;
}
sort(t+1,t+cnt+1);
for (int i=1;i<=cnt;i++) level[t[i]]=i;
for (int i=1;i<=n;i++) p[i]=lev el[p[i]];
}
inline int getdp(){
now=1;
for (int i=1;i<=cnt;i++){
if (i>p[1])dp[now][i]=m1;
else if (i<p[1])dp[now][i]=m2;
else dp[now][i]=0;
}
for (int i=2;i<=n;i++){
now=1-now;pre=1-now;
minv=dp[now][1]=dp[pre][1];
for (int j=2;j<=cnt;j++){
minv=min(minv,dp[pre][j]);
dp[now][j]=minv;
}
for (int j=1;j<p[i];j++)dp[now][j]+=m2;
for (int j=p[i]+1;j<=cnt;j++)dp[now][j]+=m1;
}
int res=inf;
for (int i=1;i<=cnt;i++)res=min(res,dp[now][i]);
return res;
}
void solve(){
ans=getdp();
reverse(p+1,p+n+1);
ans=min(ans,getdp());
printf("%d\n",ans);
}
int main(){
freopen ("robot.in","r",stdin);
freopen ("robot.out","w",stdout);
init();
solve();
return 0;
}

T3 下标

问题描述

Bella 同学在学习 C++的时候,有一天意外地把\(a[i]\)写成了\(i[a]\),发现程

序居然还能正常地编译和运行!(如果你现在做题做累了,不妨拿出半分钟时间

试试看这是不是真的! )

通过进一步的实验,Bella认为,对于任意的两个合法的表达式\(A\)和\(B\),表

达式\(A[B]\)与\(B[A]\)是等价的。

并且,等价是具有传递性的。例如,\(a[b[c]]\)和\(c[b][a]\)是等价的,因为这

两个表达式都和\(a[c[b]]\)等价。

现在给你一些合法的表达式,其中只会出现小写字母与方括号。你需要对每

个表达式进行若干次这样的等价变换,得到一个字典序尽可能小的表达式。

更正式地,所有可能出现的表达式恰好能由如下上下文无关文法从符号

Expr生成:

\[Expr -> Term | Expr [ Expr ]
\]

\[Term -> Char | Char Term
\]

\[Char -> a | b | ... | z
\]

而每次的等价变换,是将一个形如\(Expr1[Expr2]\)的式子变为

\(Expr2[Expr1]\),并且要求\(Expr1\)与\(Expr2\)都能由\(Expr\)生成。

输入格式

输入文件的第一行只包含一个正整数\(T\),表示该输入文件的数据个数。

接下来\(T\)行,每行一个字符串,表示一个合法的表达式。

输出格式

对于每个输入数据,输出一行,表示所能得到的字典序最小的表达式。

样例

样例输入
aaa[bbb]
a[b[abbb]]
b[a[azzz]]
x[a][b[a]]
样例输出
aaa[bbb]
a[abbb[b]]
a[azzz][b]
a[b]a[x]]

题解

将输入字符串的括号进行匹配,找到每个右括号对应的左括号。记

匹配后的字符串为\(S=aaa[A][B]\),其中\(A\)和\(B\)都为\(expr,B\)右侧的括号为整个字符串

的结尾,\(B\)左侧的括号是与最后的右括号匹配的左括号。定义过程\(solve(S)\)表示寻找

字符串 S 的最小字典序表示,首先递归调用\(solve(aaa[A])与solve(B)\)然后再比较

\(aaa[A][B]\)与\(B[aaa[A]]\)的字典序, 将\(S\)变为这两者中较小的一个。时间复杂度\(O(n^2)\),

期望得分 80 分。在 80 分做法的基础上,使用链表控制整个字符串,记录每个字符串

的后继元素,这可以使得等价变换的时间复杂度变为\(O(1)\)即可。

#include <iostream>
#include <cstdio>
#include <string>
#include <cstring> using namespace std;
const int maxn = 100010;
int sta[maxn], len, top, mp[maxn];
string s;
string work(int l, int r){
string res = "";
if(s[r] != ']'){
for(int i = l; i <= r; i++){
res += s[i];
}
return res;
}
string s1 = work(l, mp[r] - 1);
string s2 = work(mp[r] + 1, r - 1);
if(s1 > s2){
swap(s1, s2);
}
res += s1;
res += '[';
res += s2;
res += ']';
return res;
}
int main(){
int t;
scanf("%d", &t);
while(t--){
cin >> s;
len = s.size();
for(int i = len - 1; i >= 0; i--){
if(s[i] == ']'){
sta[top++] = i;
}
if(s[i] == '['){
mp[sta[--top]] = i;
}
}
cout << work(0, len - 1) << endl;;
}
return 0;
}

CCF-NOIP-2018 提高组(复赛) 模拟试题(三)的更多相关文章

  1. CCF-NOIP-2018 提高组(复赛) 模拟试题(九)(2018 CSYZ长沙一中)

    T1 Circle [问题描述] 小 w 的男朋友送给小 w 一个 n 个点 m 条边的图,并且刁难小 w 要她找出点数最少的正环. 小 w 不会做,于是向你求助. [输入格式] 第一行两个整数\(n ...

  2. 冲刺NOIP2015提高组复赛模拟试题(五)2.道路修建

    2.道路修建 描述 Description liouzhou_101最悲痛的回忆就是NOI2011的道路修建,当时开了系统堆栈,结果无限RE… 出于某种报复心理,就把那题神奇了一下: 在 Z星球上有N ...

  3. CCF-NOIP-2018 提高组(复赛) 模拟试题(四)

    T1 贪吃蛇 [问题描述] 贪吃蛇是一个好玩的游戏.在本题中,你需要对这个游戏进行模拟. 这个游戏在一个 \(n\) 行 \(m\) 列的二维棋盘上进行. 我们用 \((x, y)\) 来表示第 \( ...

  4. CCF-NOIP-2018 提高组(复赛) 模拟试题(七)

    T1 Adjoin [问题描述] 定义一种合法的\(0-1\)串:串中任何一个数字都与\(1\)相邻.例如长度为$ 3 的 0-1 $串中,\(101\)是非法的,因为两边的\(1\)没有相邻的\(1 ...

  5. CCF-NOIP-2018 提高组(复赛) 模拟试题(一)

    T1 帽子戏法 问题描述 小 Y 有一个\(n*n*n\)的"帽子立方体" ,即一个\(n\)层的立方体,每层的帽子都 可以排成\(n*n\)的矩阵. "帽子立方体&qu ...

  6. 破译情报-NOIP2016提高组复赛模拟试题

    [题目描述] 最近国安人员截获了一份 RB 国的秘密情报, 全文都是经过加密的,每个单 词都很长.破译人员想到先把单词化简一下,方法是把每个单词尽量取短些的前 缀,但所取的前缀不能是其他单词的前缀. ...

  7. 冲刺NOIP2015提高组复赛模拟试题(五) 3.破坏基地

    3.破坏基地 描述 Description 在Z国和W国之间一直战火不断. 好不容易,W国的间谍把完整的Z国的军事基地的地图到手了. 于是W国决定再次出击,一举击破Z国的防线. W国认真研究了Z国的地 ...

  8. 冲刺NOIP2015提高组复赛模拟试题(五)1.数学作业

    1. 数学作业 [问题描述] 路人丙的数学老师非常乏力,他喜欢出一些非常乏力的数学题来为难乏力的学生们.这次数学老师布置了一堆的数学题作为作业,而且这些数学题有个共同的特点是都求C(N,M)中不同质因 ...

  9. CCF-NOIP-2018 提高组(复赛) 模拟试题(五)

    T1 相遇 [问题描述] 在一场奇怪的梦里,小 Y 来到了一个神奇的国度.这个国度可以用一根数轴表示,小 Y 在 N 处,而小 Y 想吃的美食在 K 处.小 Y 有两种方式移动, 一种叫做步行, 一种 ...

随机推荐

  1. eclipce导出项目发布到tomcat

    1.右击项目-Except 2.在弹出框中输入“WAR file” 3.点击“next” 在Destinatin选择保存路径,即可 4.将保存的文件复制到tomcat下,启动tomcat之后,会自动解 ...

  2. 手机验证码免费10条\java、C#、html....

    使用互亿无线短信接口网址:http://www.ihuyi.com/. 首先第一步,进行注册 第二步:注册成功后进来的页面 第三步:实名认证 第四步:个人信息 等待认证成功后才能继续操作 第五步:进行 ...

  3. Android学习笔记_66_图片处理专题

    1.图片缩放:不解析整个图片信息. public class DemoActivity extends Activity { @Override public void onCreate(Bundle ...

  4. 微信开发----JS-SDK接口

    2018.03.15:GitHub下载代码 208.3.6:更新:我们不再使用JosnHelp返回字典类或者强类型,而是直接返回动态类型,这样就会方便的多. JsonHelp更新详情:微信开发---- ...

  5. js,h5页面判断客户端是ios还是安卓

    $(function(){ var u = navigator.userAgent, app = navigator.appVersion; var isAndroid = u.indexOf('An ...

  6. o'Reill的SVG精髓(第二版)学习笔记——第九章

    第九章:文本 9.1 字符:在XML文档中,字符是指带有一个数字值的一个或多个字节,数字只与Unicode标准对应. 符号:符号(glyph)是指字符的视觉呈现.每个字符都可以用很多不同的符号来呈现. ...

  7. iOS | FMDB快速上手

    任何的开发都或多或少的接触到数据库,而在IOS中一般使用的是SQLite数据库,这是一个轻量功能较为不错的数据库.而现在用到比较多的第三方数据库操作框架就是FMDB.废话不多说,相信查找到这篇文章的都 ...

  8. D - 湫湫系列故事——减肥记II

    虽然制定了减肥食谱,但是湫湫显然克制不住吃货的本能,根本没有按照食谱行动! 于是,结果显而易见… 但是没有什么能难倒高智商美女湫湫的,她决定另寻对策——吃没关系,咱吃进去再运动运动消耗掉不就好了? 湫 ...

  9. 在CentOS 7上搭建Docker环境

      Preface       We commonly use VMware or VirtualBox to install our Virtual Machines before.For the ...

  10. 上传文件到阿里云linux服务器

    在“运行”中输入cmd,打开控制台,切换到刚才Putty的安装目录下,我的是E:\Putty,然后输入pscp命令,我们需要这个命令来实现文件的上传.如下图所示,命令格式为: pscp D:\recy ...