Educational Codeforces Round 63 (Rated for Div. 2)

传送门


A. Reverse a Substring

题意:

  给你一串 s,让你判断能否通过反转区间[l,r]的元素,使得反转后的串的字典序小于 s;

  如果能,输出 "YES",并输出任意的 l,r,并不需要所输出的 l,r 是所有满足条件的 l',r' 中的字典序最小的;

  反之,输出"NO";

  例如,如果串 s = "abaa"

  你可以反转[2,3]得到 "aaba"

  也可以反转[2,4]得到字典序更小的 "aaab"

  输出其中一个答案即可;

AC代码:

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define INF 0x3f3f3f3f
 4 #define INFull ~0ULL
 5 #define ll long long
 6 #define ull unsigned long long
 7 #define mem(a,b) memset(a,b,sizeof(a))
 8 const int maxn=3e5+50;
 9 
10 int n;
11 char s[maxn];
12 
13 void Solve()
14 {
15     int len=strlen(s+1);
16     int ans=len+1;
17     for(int i=2;i <= len;++i)
18         if(s[i] < s[i-1])//求出第一个下降的位置
19         {
20             ans=i;
21             break;
22         }
23     if(ans == len+1)//如果没找到下降的位置
24         printf("NO\n");
25     else
26     {
27         printf("YES\n");
28         printf("%d %d\n",ans-1,ans);//反转区间[ans-1,ans]
29     }
30 }
31 int main()
32 {
33 //    freopen("C:\\Users\\hyacinthLJP\\Desktop\\in&&out\\contest","r",stdin);
34     scanf("%d",&n);
35     scanf("%s",s+1);
36     Solve();
37     return 0;
38 }
View Code

思考:

  如果题干改为求反转区间[l,r]使得得到的串的字典序最小呢?

  该怎么求呢?


B. Game with Telephone Numbers

题意

  给出你一个包含 n 个数字的串 s(n为奇数);

  Vasya 和 Petya 个从中选取 (n-11)/2 个数字,删去,游戏从Vasya开始;

  问 Vasya 能否必胜,必胜的条件是,删除后的串,s[0]='8';

AC代码:

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define INF 0x3f3f3f3f
 4 #define INFull ~0ULL
 5 #define ll long long
 6 #define ull unsigned long long
 7 #define mem(a,b) memset(a,b,sizeof(a))
 8 const int maxn=3e5+50;
 9 
10 int n;
11 char s[maxn];
12 
13 char* Solve()
14 {
15     int len=strlen(s);
16     int need=(n-11)/2;//每人需要删除need元素
17     int tot8=0;//s中'8'的总个数
18     
19     for(int i=0;i < len;++i)
20         if(s[i] == '8')
21             tot8++;
22     if(tot8 <= need)//8的个数小于等于删除的个数
23         return "NO";
24         
25     //最坏的情况是,Petya删除need个8
26     //那么,Vasya就需要将第need+1个8前的其他数字都删去
27     int tot=0;//第need+1个8前的非'8'得个数
28     int cur=need+1;
29     for(int i=0;cur > 0 && i < len;++i)
30     {
31         if(s[i] != '8')
32             tot++;
33         else
34             cur--;
35     }
36     if(tot <= need)//可以删除这tot个非'8'数
37         return "YES";
38     else
39         return "NO";
40 }
41 int main()
42 {
43 //    freopen("C:\\Users\\hyacinthLJP\\Desktop\\in&&out\\contest","r",stdin);
44     scanf("%d",&n);
45     scanf("%s",s);
46     printf("%s\n",Solve());
47     return 0;
48 }
View Code

C. Alarm Clocks Everywhere

题意:

  Ivan 在睡觉前定了闹铃;

  闹铃在 a 时刻开始出声,每隔 b 时刻响一次;

  Ivan 需要闹铃在 x1,x2,....,xn 时刻提醒他;

  给出你 x1,x2,....,xn 和闹铃的间隔时刻 p1,p2,....,pm

  假设闹钟在 a 开始出声,能否在给出的时间间隔内使闹钟响的时刻满足Ivan的需求; 

  如果能,输出开始出声的时刻a和时间间隔对应在在p中的下标;

AC代码:

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define INF 0x3f3f3f3f
 4 #define INFull ~0ULL
 5 #define ll long long
 6 #define ull unsigned long long
 7 #define mem(a,b) memset(a,b,sizeof(a))
 8 const int maxn=3e5+50;
 9 
10 int n,m;
11 ll x[maxn];
12 ll p[maxn];
13 
14 ll GCD(ll a,ll b)
15 {
16     return a == 0 ? b:GCD(b%a,a);
17 }
18 
19 char* Solve()
20 {
21     ll gcd=x[2]-x[1];
22     for(int i=3;i <= n;++i)
23         gcd=GCD(gcd,x[i]-x[i-1]);//求所有时间间隔的GCD
24     int ans=0;
25     for(int i=1;i <= m;++i)
26         if(gcd%p[i] == 0)//如果找到gcd的因子
27         {
28             ans=i;
29             break;
30         }
31     if(ans == 0)
32         printf("NO\n");
33     else
34     {
35         printf("YES\n");
36         printf("%I64d %d\n",x[1],ans);//从x[1]时刻开始,每隔p[ans]时刻提醒一次可以满足条件
37     }
38 }
39 int main()
40 {
41 //    freopen("C:\\Users\\hyacinthLJP\\Desktop\\in&&out\\contest","r",stdin);
42     scanf("%d%d",&n,&m);
43     for(int i=1;i <= n;++i)
44         scanf("%lld",x+i);
45     for(int i=1;i <= m;++i)
46         scanf("%lld",p+i);
47     Solve();
48     return 0;
49 }
View Code

猜你喜欢

转载自www.cnblogs.com/violet-acmer/p/10757711.html