NOIP2014-5-17模拟赛

Problem 1 双色球(ball.cpp/c/pas)

【题目描述】

机房来了新一届的学弟学妹,邪恶的chenzeyu97发现一位学弟与他同名,于是他当起了善良的学长233

“来来来,学弟,我考你道水题检验一下你的水平……”

一个栈内初始有n个红色和蓝色的小球,请你按照以下规则进行操作

  1. 只要栈顶的小球是红色的,将其取出,直到栈顶的球是蓝色
  2. 然后将栈顶的蓝球变成红色
  3. 最后放入若干个蓝球直到栈中的球数为n

以上3步骤为一次操作

如栈中都是红色球,则操作停止,请问几次操作后停止

chenzeyu97出完题发现他自己不能AC所以想请你帮忙

【输入格式】

第一行为一个整数n,表示栈的容量为n

第二行为一个字符串,第i个字符表示自顶向下的第i个球的颜色,R代表红色,B代表蓝色

【输出格式】

一个整数表示操作数

【样例输入】

样例1:

3

RBR

样例2:

4

RBBR

【样例输出】

样例1:2

样例2:6

【样例解释】

样例1:

样例2:

【数据范围】

50%的数据,1<=n<=20

100%的数据,1<=n<=50

Problem 2 魔方(cube.cpp/c/pas)

【题目描述】

ccy(ndsf)觉得手动复原魔方太慢了,所以他要借助计算机。

ccy(ndsf)家的魔方都是3*3*3的三阶魔方,大家应该都见过。

(3的“顺时针”改为“逆时针”,即3 4以图为准。)
ccy(ndfs)从网上搜了一篇攻略,并找人翻译成了他自己会做的方法。现在告诉你他的魔方情况,以及他从网上搜到的攻略,请你求出最后魔方变成什么样子。

【输入格式】
   第一行,一串数字,表示从网上搜到的攻略。
   下面6*3行,每行3个数字,每三行表示魔方一个面的情况,六个面的顺序是前、后、左、右、上、下。

【输出格式】
   6*3行,表示处理后的魔方,形式同输入。

【样例输入】

23
121
221
111
123
321
111
123
321
132
132
231
132
121
112
233
332
111
333

【样例输出】

123
222
113
212
321
113
122
321
132
121
333
121
211
312
113
331
111
331

【样例解释】

【数据范围】

40%的数据,攻略的长度小于5且仅有4种操作的其中一种

100%的数据,攻略的长度小于100

Problem 3 czy的后宫(harem.cpp/c/pas)

【题目描述】

czy要妥善安排他的后宫,他想在机房摆一群妹子,一共有n个位置排成一排,每个位置可以摆妹子也可以不摆妹子。有些类型妹子如果摆在相邻的位置(隔着一个空的位置不算相邻),就不好看了。假定每种妹子数量无限,求摆妹子的方案数。

【输入格式】

输入有m+1行,第一行有两个用空格隔开的正整数n、m,m表示妹子的种类数。接下来的m行,每行有m个字符1或0,若第i行第j列为1,则表示第i种妹子第j种妹子不能排在相邻的位置,输入保证对称。(提示:同一种妹子可能不能排在相邻位置)。

【输出格式】

输出只有一个整数,为方案数(这个数字可能很大,请输出方案数除以1000000007的余数。

【样例输入】

2 2

01

10

【样例输出】

7

【样例说明】

七种方案为(空,空)、(空,1)、(1、空)、(2、空)、(空、2)、(1,1)、(2,2)。

【数据范围】

20%的数据,1<n≤5,0<m≤10。

60%的数据,1<n≤200,0<m≤100。

100%的数据,1<n≤1000000000,0<m≤100。

注:此题时限1.5s是因为本评测机跑太慢,大家正常做

但写的太丑可能T一俩个点

Problem 4 mex(mex.cpp/c/pas)

【题目描述】

【输入格式】

【输出格式】

【样例输入】

7 5

0 2 1 0 1 3 2

1 3

2 3

1 4

3 6

2 7

【样例输出】

3

0

3

2

4

【样例解释与数据范围】



T1:

这题一开始看数据范围这么小,于是乎直接模拟,T5个点

 1 #include<cstdio>
 2 #include<cstdlib>
 3 #include<algorithm>
 4 #include<cstring>
 5 #define MAXN 55
 6 using namespace std;
 7 int stack[MAXN],top=0;
 8 int cnt;
 9 int n;
10 int ans=0;
11 int main()
12 {
13     scanf("%d",&n);
14     // 1 red 2 blue;
15     for(int i=n;i>=1;i--){
16         char c;
17         scanf(" %c",&c);
18         if(‘R‘==c){
19             stack[i]=1;
20             cnt++;
21         }
22         else{
23             stack[i]=2;
24         }
25     }
26     top=n;
27     while(1){
28         ans++;
29         while(1==stack[top]&&top){
30             top--;
31             cnt--;
32         }
33         if(2==stack[top]&&top){
34             stack[top]=1;
35             cnt++;
36         }
37         for(int i=top+1;i<=n;i++){
38             stack[i]=2;
39         }
40         top=n;
41         if(cnt==n){
42             break;
43         }
44     }
45     printf("%d\n",ans);
46     return 0;
47 }

Code1

后来发现其实是找规律的:

对于一个栈,我们只考虑从栈顶到第一个blue,即RRRRB,因为所有操作不可能干到这个B底下,

我们姑且无视B下面的东西吧

然后发现操作1次为BBBBR,再次无视这个R,变成了BBBB

然后发现操作分别变成RBBB BRBB RRBB ……

如同0000 1000 0100 1100 ……

规律出来了,对于栈中自上向下第i个B,把它变成R需要2^(i-1),然后依次处理即可

注意:用long long的时候就不可以把int类型的i直接(1<<(i-1)),会炸的

 1 #include<cstdio>
 2 #include<cstdlib>
 3 #include<algorithm>
 4 #include<cstring>
 5 #define ll long long
 6 using namespace std;
 7 int n;
 8 ll ans;
 9 ll Power(int p){
10     ll ret=1;
11     for(int i=1;i<=p;i++){
12         ret*=2;
13     }
14     return ret;
15 }
16 int main()
17 {
18     char c;
19     scanf("%d",&n);
20     for(int i=0;i<n;i++){
21         scanf(" %c",&c);
22         if(‘B‘==c){
23             ans+=Power(i);
24         }
25     }
26     printf("%lld\n",ans);
27     return 0;
28 }

Code2



T2:

暂且不提供题解



T3:

设f[i][j]表示i个座位,必须以第j个妹子为结尾的方案

然后f[i][j]=∑f[i-1][k] (j,k不矛盾)

当然矩阵快速幂优化即可,详见代码

注意:

1,妹子可以为空,那么直接m++即可,多出来的矩阵用1补足

2,输入的01矩阵和转移矩阵正好反的

3,对于矩阵较大的内存,最好不要用递归快速幂,直接用循环即可

4,切记要开long long!!!

 1 #include<cstdio>
 2 #include<cstdlib>
 3 #include<algorithm>
 4 #include<cstring>
 5 #include<iostream>
 6 #define MAXN 105
 7 #define MOD 1000000007
 8 #define ll long long
 9 using namespace std;
10 struct Mat{
11     int len;
12     ll s[MAXN][MAXN];
13     Mat(){
14         len=0;
15         memset(s,0,sizeof(s));
16     }
17     void operator *= (const Mat &A){
18         Mat t;
19         len=A.len;
20         for(int i=1;i<=len;i++){
21             for(int j=1;j<=len;j++){
22                 for(int k=1;k<=len;k++){
23                     t.s[i][j]=(t.s[i][j]+(s[i][k]*A.s[k][j])%MOD)%MOD;
24                 }
25             }
26         }
27         for(int i=1;i<=len;i++){
28             for(int j=1;j<=len;j++){
29                 s[i][j]=t.s[i][j];
30             }
31         }
32     }
33     void operator = (const Mat &A){
34         len=A.len;
35         for(int i=1;i<=len;i++){
36             for(int j=1;j<=len;j++){
37                 s[i][j]=A.s[i][j];
38             }
39         }
40     }
41 };
42 int n,m;
43 Mat Power(Mat A,int p){
44     Mat ret;
45     ret.len=m+1;
46     for(int i=1;i<=ret.len;i++){
47         ret.s[i][i]=1;
48     }
49     Mat t; t=A;
50     for(;p;p>>=1){
51         if(p&1){
52             ret*=t;
53         }
54         t*=t;
55     }
56     return ret;
57 }
58 int main()
59 {
60 //    freopen("harem2.in","r",stdin);
61     Mat A;
62     scanf("%d%d",&n,&m);
63     if(1==n){
64         printf("%d\n",m+1);
65     }
66     char ch[MAXN]={0};
67     for(int i=1;i<=m;i++){
68         scanf("%s",ch+1);
69         for(int j=1;j<=m;j++){
70             if(‘0‘==ch[j])
71             A.s[i][j]=1;
72         }
73     }
74     A.len=m+1;
75     for(int i=1;i<=m+1;i++){
76         A.s[m+1][i]=A.s[i][m+1]=1;
77     }
78     Mat t=Power(A,n-1);
79     ll ans=0;
80     int len=t.len;
81     for(int i=1;i<=len;i++){
82         for(int j=1;j<=len;j++){
83             ans=(ans+t.s[i][j])%MOD;
84         }
85     }
86     cout<<ans<<endl;
87     return 0;
88 }

Code3



T4:

我当时用莫队算法+暴力,60分

 1 #include<cstdio>
 2 #include<cstdlib>
 3 #include<algorithm>
 4 #include<cstring>
 5 #include<cmath>
 6 #define MAXN 200005
 7 using namespace std;
 8 struct Ask{
 9     int L,R;
10     int lb,id;
11     int ans;
12     Ask(){
13         L=R=lb=ans=0;
14     }
15 };
16 bool comp1(const Ask &p1,const Ask &p2){
17     if(p1.lb!=p2.lb){
18         return (p1.lb<p2.lb);
19     }
20     else{
21         return (p1.R<p2.R);
22     }
23 }
24 bool comp2(const Ask &p1,const Ask &p2){
25     return (p1.id<p2.id);
26 }
27 Ask s[MAXN];
28 int n,T;
29 int b[MAXN];
30 int a[MAXN];
31 int main()
32 {
33 //    freopen("data.in","r",stdin);
34     scanf("%d%d",&n,&T);
35     int size=sqrt(n);
36     for(int i=1;i<=n;i++){
37         scanf("%d",&a[i]);
38     }
39     for(int i=1;i<=T;i++){
40         scanf("%d%d",&s[i].L,&s[i].R);
41         s[i].lb=s[i].L/size;
42         s[i].id=i;
43     }
44     sort(s+1,s+T+1,comp1);
45     int x=1,y=0;
46     int t=0;
47     for(int i=1;i<=T;i++){
48         int L=s[i].L,R=s[i].R;
49         if(x<L){
50             for(int j=x;j<L;j++){
51                 b[a[j]]--;
52                 if(!b[a[j]]){
53                     t=min(t,a[j]);
54                 }
55             }
56         }
57         else if(x>L){
58             for(int j=x-1;j>=L;j--){
59                 if(!b[a[j]]&&t==a[j]){
60                     for(t++;;t++){
61                         if(!b[t]){
62                             break;
63                         }
64                     }
65                 }
66                 b[a[j]]++;
67             }
68         }
69         if(y<R){
70             for(int j=y+1;j<=R;j++){
71                 if(!b[a[j]]&&t==a[j]){
72                     for(t++;;t++){
73                         if(!b[t]){
74                             break;
75                         }
76                     }
77                 }
78                 b[a[j]]++;
79             }
80         }
81         else if(y>R){
82             for(int j=y;j>R;j--){
83                 b[a[j]]--;
84                 if(!b[a[j]]){
85                     t=min(t,a[j]);
86                 }
87             }
88         }
89         x=L,y=R;
90         s[i].ans=t;
91     }
92     sort(s+1,s+T+1,comp2);
93     for(int i=1;i<=T;i++){
94         printf("%d\n",s[i].ans);
95     }
96     return 0;
97 }

Code4

其实这题并不好写,原因这些数据都是离散的,搞不出来连续的,用数据结构不好维护

于是可以构造出连续的数据:Next[i]=j (a[i]==a[j]&&i<j)

然后按左节点从左到右依次解决,当左节点变化时,相应的j~Next[j]-1用线段树进行更新即可

这样可以用离线算法解决了,转化为典型的离线问题

另:线段树切记开4倍啊QAQ

  1 #include<cstdio>
  2 #include<cstdlib>
  3 #include<algorithm>
  4 #include<cstring>
  5 #define MAXN 200005
  6 #define INF 0x7f7f7f7f
  7 using namespace std;
  8 int mex[MAXN];
  9 int n,m;
 10 int dat[MAXN*4],tag[MAXN*4];
 11
 12 void build(int k,int L,int R){
 13 //build:L+1==R return
 14     if(L+1==R){
 15         dat[k]=mex[L];
 16         return ;
 17     }
 18     build(k<<1,L,(L+R)>>1);
 19     build(k<<1|1,(L+R)>>1,R);
 20 }
 21 void pushdown(int k){
 22     int lc=(k<<1),rc=(k<<1|1);
 23     dat[lc]=min(dat[lc],tag[k]);
 24     dat[rc]=min(dat[rc],tag[k]);
 25     tag[lc]=min(tag[lc],tag[k]);
 26     tag[rc]=min(tag[rc],tag[k]);
 27     tag[k]=INF;
 28 }
 29 void update(int a,int b,int k,int L,int R,int t){
 30     if(b<=L||R<=a){
 31         return;
 32     }
 33     else if(a<=L&&R<=b){
 34         dat[k]=min(dat[k],t);
 35         tag[k]=min(tag[k],t);
 36     }
 37     else{
 38         if(tag[k]!=INF){
 39             pushdown(k);
 40         }
 41         update(a,b,k<<1,L,(L+R)>>1,t);
 42         update(a,b,k<<1|1,(L+R)>>1,R,t);
 43     }
 44 }
 45 int find(int x,int k,int L,int R){
 46     if(L+1==R){
 47         return dat[k];
 48     }
 49     int mid=(L+R)>>1;
 50     if(tag[k]!=INF){
 51         pushdown(k);
 52     }
 53     if(x<mid){
 54         return find(x,k<<1,L,mid);
 55     }
 56     else{
 57         return find(x,k<<1|1,mid,R);
 58     }
 59 }
 60 struct Ask{
 61     int L,R;
 62     int id,ans;
 63     Ask(){
 64         L=R=id=ans=0;
 65     }
 66 }s[MAXN];
 67 bool comp1(const Ask &p1,const Ask &p2){
 68     return (p1.L<p2.L);
 69 }
 70 bool comp2(const Ask &p1,const Ask &p2){
 71     return (p1.id<p2.id);
 72 }
 73 int a[MAXN],b[MAXN];
 74 int Next[MAXN],first[MAXN];
 75
 76 int main()
 77 {
 78 //    freopen("T1.in","r",stdin);
 79 //    freopen("my.out","w",stdout);
 80     memset(dat,0x7f,sizeof(dat));
 81     memset(tag,0x7f,sizeof(tag));
 82 //    freopen("data.in","r",stdin);
 83     scanf("%d%d",&n,&m);
 84     for(int i=1;i<=n;i++){
 85         scanf("%d",&a[i]);
 86     }
 87     for(int i=1;i<=m;i++){
 88         scanf("%d%d",&s[i].L,&s[i].R);
 89         s[i].id=i;
 90     }
 91     int k=0;
 92     for(int i=1;i<=n;i++){
 93         b[a[i]]=1;
 94         while(b[k]){
 95             k++;
 96         }
 97         mex[i]=k;
 98     }
 99     build(1,1,n+1);
100     for(int i=n;i>=1;i--){
101         Next[i]=first[a[i]];
102         first[a[i]]=i;
103         if(!Next[i]){
104             Next[i]=n+1;
105         }
106     }
107     sort(s+1,s+m+1,comp1);
108     int nL=1;
109     for(int i=1;i<=m;i++){
110         if(nL<s[i].L){
111             for(int j=nL;j<s[i].L;j++){
112                 update(j,Next[j]-1+1,1,1,n+1,a[j]);
113             }
114             nL=s[i].L;
115         }
116 //        for(int j=1;j<=n;j++){
117 //            printf("%d ",find(j,1,1,n+1));
118 //        }
119 //        printf("\n");
120         s[i].ans=find(s[i].R,1,1,n+1);
121     }
122     sort(s+1,s+m+1,comp2);
123     for(int i=1;i<=m;i++){
124         printf("%d\n",s[i].ans);
125     }
126     return 0;
127 }

Code5

时间: 2024-08-28 12:43:31

NOIP2014-5-17模拟赛的相关文章

9.17模拟赛

T1 巧克力棒 题目描述 LYK 找到了一根巧克力棒,但是这根巧克力棒太长了,LYK 无法一口吞进去. 具体地,这根巧克力棒长为nn,它想将这根巧克力棒折成nn段长为11的巧克力棒,然后慢慢享用. 它打算每次将一根长为kk的巧克力棒折成两段长为aa和bb的巧克力棒,此时若a=ba=b,则LYK 觉得它完成了一件非常困难的事,并会得到11点成就感. LYK 想知道一根长度为nn的巧克力棒能使它得到最多几点成就感. 输入输出格式 输入格式: 第一行一个数nn. 输出格式: 一个数表示答案. 输入输出

【BZOJ】【2741】【FOTILE模拟赛】L

可持久化Trie+分块 神题……Orz zyf & lyd 首先我们先将整个序列搞个前缀异或和,那么某一段的异或和,就变成了两个数的异或和,所以我们就将询问[某个区间中最大的区间异或和]改变成[某个区间中 max(两个数的异或和)] 要是我们能将所有[l,r]的答案都预处理出来,那么我们就可以O(1)回答了:然而我们并不能. 一个常见的折中方案:分块! 这里先假设我们实现了一个神奇的函数ask(l,r,x),可以帮我们求出[l,r]这个区间中的数,与x最大的异或值. 我们不预处理所有的左端点,我

10.30 NFLS-NOIP模拟赛 解题报告

总结:今天去了NOIP模拟赛,其实是几道USACO的经典的题目,第一题和最后一题都有思路,第二题是我一开始写了个spfa,写了一半中途发现应该是矩阵乘法,然后没做完,然后就没有然后了!第二题的暴力都没码QAQ 现在我来写解题报告了,有点饿了QAQ.. 第一题 题目 1: 架设电话线 [Jeffrey Wang, 2007] 最近,Farmer John的奶牛们越来越不满于牛棚里一塌糊涂的电话服务,于 是,她们要求FJ把那些老旧的电话线换成性能更好的新电话线.新的电话线架设 在已有的N(2 <=

【题解】PAT团体程序设计天梯赛 - 模拟赛

由于本人愚笨,最后一题实在无力AC,于是只有前14题的题解Orz 总的来说,这次模拟赛的题目不算难,前14题基本上一眼就有思路,但是某些题写起来确实不太容易,编码复杂度有点高~ L1-1 N个数求和 设计一个分数类,重载加法运算符,注意要约分,用欧几里得算法求个最大公约数即可. 1 #include <cstdio> 2 3 long long abs(long long x) 4 { 5 return x < 0 ? -x : x; 6 } 7 8 long long gcd(long

[铁一中OI模拟赛]2017.8.19 Day1

T1 小Z的情书 题目链接 思考: 题目主要难度在于旋转后的位置如何,在手写了样例之后不难发现规律. #include <cstdio> #include <cstring> #define up(a,b,c) for(register int c=a;c<=b;++c) #define down(a,b,c) for(register int c=a;c>=b;--c) const int Maxn=1005; int n; bool Map[Maxn][Maxn],

bzoj2741: 【FOTILE模拟赛】L

2741: [FOTILE模拟赛]L Time Limit: 15 Sec  Memory Limit: 162 MBSubmit: 2679  Solved: 766[Submit][Status][Discuss] Description FOTILE得到了一个长为N的序列A,为了拯救地球,他希望知道某些区间内的最大的连续XOR和. 即对于一个询问,你需要求出max(Ai xor Ai+1 xor Ai+2 ... xor Aj),其中l<=i<=j<=r. 为了体现在线操作,对于一

140725模拟赛总结

A:hdu4847    字符串匹配第一想法是KMP,写了好长时间结果还TLE了-_-||,实际上用个简单的枚举判断就能解决.因为待验证的字符串"doge"很小.写A题的时候还被输入卡了半天.Tips1:输入至文件结尾(eof)的常用方法:     while (cin>>a)        //最常用的     while (cin.getline(s,30))    //按行读入前30个字符.空格也读入    getline(cin,s)        //和getli

NOIP模拟赛 6.29

2017-6-29 NOIP模拟赛 Problem 1 机器人(robot.cpp/c/pas) [题目描述] 早苗入手了最新的Gundam模型.最新款自然有着与以往不同的功能,那就是它能够自动行走,厉害吧. 早苗的新模型可以按照输入的命令进行移动,命令包括‘E’.‘S’.‘W’.‘N’四种,分别对应东南西北.执行某个命令时,它会向对应方向移动一个单位.作为新型机器人,它可以执行命令串.对于输入的命令串,每一秒它会按命令行动一次.执行完命令串的最后一个命令后,会自动从头开始循环.在0时刻时机器人

2017.11.25【NOIP提高组】模拟赛A组

2017.11.25[NOIP提高组]模拟赛A组 T1 3467. [NOIP2013模拟联考7]最长上升子序列(lis) T2 3468. [NOIP2013模拟联考7]OSU!(osu) T3 3472. [NOIP2013模拟联考8]匹配(match) T1 有转移方程f[i]=max{f[j]}+1,a[j]<a[i] 可以用线段树+离散化维护这个方程,因为涉及以往状态可以用主席树维护 打太丑爆空间了 Code 1 #include<cstdio> 2 #include<c

11.27 模拟赛

并没有人做的模拟赛... 出题人hx,,, T1:就是上一道矩阵乘法 数学题 T2: 一个数列中 一个区间满足,存在一个k(L <= k <= R),并且对于任意的i (L <= i <= R),ai都能被ak整除 这样的一个特殊区间 [L, R]价值为R - L 想知道序列中所有特殊区间的最大价值是多少,而有多少个这样的区间呢 这些区间又分别是哪些呢 输出每个区间的L 思路: 用两个ST表分别求一段区间的gcd和最小值 然后可以二分答案 check的时候枚举左端点,判断在这段区间