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 }
View Code

  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 }
View Code

  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 }
View Code

  当时最开始做的时候,一直在想怎么剪枝之类的,写的特别恶心,最后还炸了,似乎把最基本的给忘了,大佬们说的真的很对,想要些正解,首先得明确暴力是怎么写的吧,有一种勿忘初心的感觉,防止自己走偏了。

  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 }
View Code
原文地址:https://www.cnblogs.com/yuelian/p/9061531.html