5.16欢乐赛
Posted 天下风云出我辈
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了5.16欢乐赛相关的知识,希望对你有一定的参考价值。
机房大佬改编的题,给高一的考试用的,去上课的时候教练让我们也做了做,确实是很生疏了,写下一些当时犯得错误吧
T1:
Give fen(nixiofyy) Description Yy:这题怎么做啊? Ff:自己想。 Yy:这题怎么做啊? Ff:这么简单的题都不会啊! Yy:这题怎么做啊? Ff: 这不就是那个******。 一日,再一次被bs之后,yy终于忍无可忍了。决定出点题难住ff,好打压一下ff嚣张的气焰。 不过,由于yy的智商有限,只会加减法,经过商讨,总是让ff回答诸如a+b或者a-b之类的问题,似乎难不住他。终于,yy想到一个很NB的办法:让他算a+?=b。yy:这么NB的难题都被我想到了,哈哈! Ff:这么简单的题都不会,不就是…… Input 输入一个等式,形如A+B=C或A-B=C。给定其中的两个数,请确定其中的第三个数。其中0<=A,B,C<10000000000,没有给定的数用一个单独的“?”表示,等式中没有多余空格。 Output 直接输出要求的第三个数,用回车结尾。 Sample Input 1 1+2=? Sample Output 1 3 Sample Input 2 1+?=3 Sample Output 2 2
这题,感觉对于会写读入优化的人来说都是很简单的,直接处理一下字符串判断一下问号在哪里就ok了
代码:
1 #include<iostream> 2 #include<cstring> 3 #include<cstdlib> 4 #include<cstdio> 5 #include<string> 6 using namespace std; 7 string s; 8 long long a,b,c; 9 bool flag; 10 int len; 11 int p; 12 void work1() 13 { 14 p++; 15 flag= s[p]==‘+‘?1:0; 16 p++; 17 while(isdigit(s[p])) 18 { 19 b=b*10+s[p]-‘0‘;p++; 20 } 21 p++; 22 while(isdigit(s[p])&&p<len) 23 { 24 c=c*10+s[p]-‘0‘;p++; 25 } 26 if(flag)a=c-b; 27 else a=c+b; 28 printf("%lld",a); 29 exit(0); 30 } 31 void work2() 32 { 33 p++,p++; 34 while(isdigit(s[p])&&p<len) 35 { 36 c=c*10+s[p]-‘0‘;p++; 37 } 38 if(!flag)b=a-c; 39 else b=c-a; 40 printf("%lld",b); 41 exit(0); 42 } 43 int main() 44 { 45 freopen("nixiofyy.in","r",stdin); 46 freopen("nixiofyy.out","w",stdout); 47 cin>>s; 48 len=s.length(); 49 p=0; 50 if(s[p]==‘?‘)work1(); 51 while(isdigit(s[p])) 52 { 53 a=a*10+s[p]-‘0‘;p++; 54 } 55 flag= s[p]==‘+‘?1:0; 56 p++; 57 if(s[p]==‘?‘)work2(); 58 while(isdigit(s[p])) 59 { 60 b=b*10+s[p]-‘0‘;p++; 61 } 62 if(flag)c=a+b; 63 else c=a-b; 64 printf("%lld",c); 65 return 0; 66 }
T2:
yy的跳跃(yyjump) Description YY走路的时候习惯踩着井盖走。(不知道有没有人也有这种做法……) 踩井盖很爽,就像吃了一坨翔,but,yy不希望走得太慢,因此,他希望每一步走过的距离的最小值最大。为了快一点走,yy只好忍痛割爱,跳过一些井盖。但是,如果跳过太多,又会觉得不爽,因此,他决定,最多可以跳过M个井盖。 你可以认为yy的腿无限长,不用担心一步跨不到…… Input 第一行三个数L,N,M,分别表示家的位置,有N个井盖,可以跳过M个井盖。 接下来N行,每行一个数Di,表示N个井盖的位置 Output 输出一行一个数,表示最小距离的最大值。 Sample Input 25 5 2 2 11 14 17 21 Sample Output 4 样例解释: 跳过位置2和14的井盖,剩下相邻的井盖中距离最小的是4,是17到21或者21到25 数据规模: 1<=L<=1,000,000,000 0<=N<=50,000 0<=M<=N 0<Di<L 50%的数据,N<=100
很基本的二分(基本上求最大值最小,最小值最大的标准套路),做过 河中跳房子 的人应该都会做,但是蒟蒻当时想了好久才想起来到底应该怎么分,qwq,判断里面的cnt也数反了
代码:
1 #include<iostream> 2 #include<cstdio> 3 using namespace std; 4 const int maxn=50005; 5 int l,m,n; 6 int a[maxn]; 7 bool ok(int mid) 8 { 9 int pos=0,cnt=0; 10 for(int i=1;i<=n;++i) 11 { 12 if(a[i]-pos<mid) 13 { 14 cnt++;continue; 15 } 16 else pos=a[i]; 17 } 18 if(cnt>m)return 0; 19 return 1; 20 } 21 int ans; 22 int main() 23 { 24 freopen("yyjump.in","r",stdin); 25 freopen("yyjump.out","w",stdout); 26 scanf("%d%d%d",&l,&n,&m); 27 for(int i=1;i<=n;++i)scanf("%d",&a[i]); 28 n++,a[n]=l; 29 int L=0,R=l; 30 while(L<=R) 31 { 32 int mid=(L+R)>>1; 33 if(ok(mid))ans=mid,L=mid+1; 34 else R=mid-1; 35 } 36 printf("%d",ans); 37 return 0; 38 }
T3:
Colour Description 在机房的生活是如此的寂寞,以至于以yy等同志们只能够天天上农场种菜来打发时间。 Qyq日复一日地种着她的玫瑰,yy则毫不疲倦地偷着他的花……尽管天天花被偷掉一半,yy始终没有动摇他种花的决心。原来,一个宏伟计划的蓝图早已埋藏在yy的心中。 众所周知,农场的花一共有4种颜色,yy不喜欢老旧的东西,所以,yy希望每天种花的方案都不一样。特别地,yy也觉得两种一样颜色的花种在相邻的位置会很无聊。现在,yy想知道,一共有多少种花的方案。 这里要注意的是,农场的种花的位置是不规则的。因此我们给出一对一对的相邻的位置的关系。 Input 第一行两个数N和M,表示种花的位置的个数和相邻的位置的对数 接下来M行,每行一组数A,B表示A,B相邻 Output 一个数表示染色方法数 Sample Input 5 4 1 2 1 3 1 4 1 5 Sample Output 324 数据规模: 40%的数据 N<=5 100%的数据 N<=10,M<=50
唔,首先把每一块抽象成一个点,每个相邻的关系就是一条边,暴搜每一个点是哪一种颜色的话,是4^n,也就是大概100W,然后判断每条边连着的2个点是不是颜色冲突,复杂度是5000w,但是蒟蒻当时就把每条边判了2遍,导致t了几个点~~o(>_<)o ~~
1 #include<iostream> 2 #include<cstdio> 3 using namespace std; 4 const int maxn=12,maxm=55; 5 int n,m; 6 int x,y; 7 struct zhw{ 8 int from,to,last; 9 }tu[maxm<<1]; 10 int head[maxn],tot; 11 void add(int x,int y) 12 { 13 tot++,tu[tot].last=head[x],head[x]=tot,tu[tot].to=y,tu[tot].from=x; 14 } 15 int c[15]; 16 int ans; 17 void ok() 18 { 19 for(int i=1;i<=2*m;i+=2) 20 { 21 if(c[tu[i].from]==c[tu[i].to])return; 22 } 23 ans++; 24 } 25 void dfs(int x) 26 { 27 if(x>n) 28 { 29 ok(); 30 return; 31 } 32 c[x]=1,dfs(x+1); 33 c[x]=2,dfs(x+1); 34 c[x]=3,dfs(x+1); 35 c[x]=4,dfs(x+1); 36 } 37 int main() 38 { 39 freopen("colour.in","r",stdin); 40 freopen("colour.out","w",stdout); 41 scanf("%d%d",&n,&m); 42 for(int i=1;i<=m;++i) 43 { 44 scanf("%d%d",&x,&y); 45 add(x,y),add(y,x); 46 } 47 dfs(1); 48 printf("%d",ans); 49 return 0; 50 }
当时最开始做的时候,一直在想怎么剪枝之类的,写的特别恶心,最后还炸了,似乎把最基本的给忘了,大佬们说的真的很对,想要些正解,首先得明确暴力是怎么写的吧,有一种勿忘初心的感觉,防止自己走偏了。
T3:
Yy和mm(Ym) Description 由于yy长得实在是太帅了,英俊潇洒,风流倜傥,人见人爱,花见花开,车见车载。有一群MM排队看yy。每个MM都有自己独特的风格,由于yy有着一颗包容博爱的心,所以,什么风格的MM他都喜欢…… 啦啦啦 割掉 但是,yy有一个特别的要求,他不希望总是看到风格得差不多的MM,更加特别的是,如果两个MM风格完全一样,yy不会有任何意见。 现在,yy希望从去看他的MM中,去掉一些MM,从而使得相邻2个MM的风格值的差(绝对值)不为1。自然地,yy希望去掉的MM越少越好。 Input 第一行一个整数N; 第2~N+1行N个整数,第i个为ci。表示第i个MM的风格值。 Output 一个数,表示最少要去掉的MM数。 Sample Input 6 4 2 2 1 1 1 Sample Output 2 数据规模: 对于30%的数据,N≤1000,ci<=2000 对于50%的数据,N≤200000 0 ≤ ci ≤ 1000000 对于70%的数据,N≤1000000 0 ≤ ci ≤ 100000000 对于100%的数据,N≤5000000 0 ≤ ci ≤ maxlongint
把删除最少转化为留下最多。
开始写的n^2暴力,和最长不下降子序列是一个套路,只不过判断条件是如果绝对值的差不为1并且长度上满足,这个是比较好想到的,代码也简单,有30分的暴力分。
正解是,对于一个数来说,可能它的前面一个数和它差的绝对值为1,前面第二个数和它差的绝对值也为1,那么前面第3个数和它差的绝对值一定是不为1的。什么意思那?我们先假设没有一样的数挨着,那么和一个数绝对值相差为1的数只有2个,即它+1和它-1,如果我们记录下来在它前面的3个序列最长的序列,这3个序列满足的条件是结尾的数不一样,选出长度最大的三个,这样的话只需要o(n)的扫一遍,那么当前的数a[i]一定是可以放在至少一个序列的后面的,这时我们调出一个最长可以转移的序列放在他的后面,之所以是只放在一个序列的后面而不是每一个都去更新是为了满足3个序列的末尾都不一样的条件,而满足3个序列的末尾都不一样是因为上上行的分析,这三个序列由于只有末尾的数和长度不一样,所以只需要开一个结构体来存放着2个值就行了。
还有一个细节,就是如果是连续相同的2个数,那么只需要把后面一个数放到前面那个数组成的序列的后面就行了,这也是为了保证使3个序列的末尾不一样。
代码:
1 #include<algorithm> 2 #include<iostream> 3 #include<cstdio> 4 #include<cmath> 5 using namespace std; 6 const int maxn=5000005; 7 int n; 8 int a[maxn]; 9 struct zhw{ 10 int val,len; 11 }; 12 zhw b[4]; 13 bool cmp(const zhw &a,const zhw &b) 14 { 15 return a.len<b.len; 16 } 17 int main() 18 { 19 freopen("ym.in","r",stdin); 20 freopen("ym.out","w",stdout); 21 scanf("%d",&n); 22 for(int i=1;i<=n;++i)scanf("%d",&a[i]); 23 b[1]=b[2]=b[3]=(zhw){-3,0}; 24 for(int i=1;i<=n;++i) 25 { 26 for(int j=1;j<=3;++j) 27 if(abs(b[j].val-a[i])!=1&&b[j].len>=b[0].len) 28 b[0].len=b[j].len+1,b[0].val=a[i]; 29 bool flag=0; 30 for(int j=1;j<=3;++j) 31 { 32 if(b[j].val==b[0].val) 33 { 34 b[j].len=b[0].len; 35 flag=1;break; 36 } 37 }//判重那个 38 if(!flag)sort(b,b+4,cmp);//如果没有重复,那就把最短的那个去掉,把它排在最前面,在赋值覆盖掉,就相当于去掉了 39 b[0]=(zhw){-3,0}; 40 } 41 int ans=max(b[1].len,max(b[2].len,b[3].len)); 42 ans=n-ans; 43 printf("%d",ans); 44 return 0; 45 }
以上是关于5.16欢乐赛的主要内容,如果未能解决你的问题,请参考以下文章