Educational Codeforces Round 81 (Rated for Div. 2)

题目链接:https://codeforces.com/contest/1295/problem/A

A题~ 水题一枚~

题意:电子表上显示每个数字的屏幕由七块组成,(如图所示现在给你一个数字n,代表有n块可用的区域,问你可以显示的最大数字是多少?

 

题解:

如图,为显示数字0~9所需要的显示屏的数量。

用有限的显示屏显示最大的数字,那么就要保证 条件1.数字的位数最大(位数大数字一定大)条件2.相同位数的情况下,开头的数字尽可能大。

不难发现,显示数字1所需要的显示屏数量最少,所以尽可能的多显示数字1以满足条件1。

在满足上述条件的前提下,剩余的显示屏的数量必为1或0,如果剩下一个就把第一个数字1变成7即可,以满足条件2。

(实际上只会出现1和7两个数字

AC代码

 

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 int main(){
 4     
 5     int t;
 6     cin>>t;
 7     
 8     while(t--){
 9         
10         int n;
11         cin>>n;
12         
13         int p=n%2;
14         n/=2;
15         
16         for(int i=1;i<=p;i++){
17             cout<<7;
18         }
19         
20         for(int i=p+1;i<=n;i++){
21             cout<<1;
22         }
23         cout<<endl;
24         
25     }
26     
27     return 0;
28     
29 }

 

题目链接:https://codeforces.com/contest/1295/problem/B

B题~ Orz

题意:给出一个长度为n的只含01的字符串s,字符串t可以由任意多个s组成,即t=ssss....(最后一个s可以只取前面的一部分),字符串中的01带有权值,'0'计为+1,'1'计为-1,每一位对应的值为权值的前缀和。给出一个数字x,问使得权值等于x的t有几个(无限个则输出-1)?

题解:

  一开始看到题目的时候很懵逼,感觉无从下手却又有迹可循?

  感觉像是一个前缀和的题目?

  实际上确实和前缀和有点关系。

  字符串t是一个由无限个s组成的字符串,t的每一位也会有自己对应的权值(也有相应的前缀和),我们只需要找到在这个序列中,有几个位置的前缀和等于x即可。

  对于样例1

    字符串s:010010,对应的前缀和为101212,t对应的前缀和则为101212 323434 545656 ........... 9 8 9 10 9 10   11 10 11 12 11 12 ......... 不难发现有3个位置前缀和为10。

  可以发现t中的前缀和有规律可循,即a[i]=a[i-n]+a[n],(i>n)。可以通过一个简单的递推式求出后续每项的前缀和。

  但是,如果逐项推下去依次检索(即暴搜)必会TLE,就要想办法进行优化。

  通过上述递推式,可以推出,如果某个位置的前缀和a[i]==x,(i>0)则会有对应的,a[j]+k*x==x(j>n)

  也就是说,只要检验从1~n项的前缀和a[j]加k*a[n]是否等于x,是否有满足条件的k(k必须>=0)存在,如果存在,则会有一个对应数字k使第(i+k*n)项前缀和等于x,如果不存在则后续所有的第(i+k*n)项都不满足。

  如何检验呢?

  这里我使用了一种比较神奇的方法(就是瞎搞搞推出来的,推理过程不赘述)——取模。

  如果满足条件,x一定比a[j]多k个a[n],那么只要x和a[j]模a[n]的结果相同(即把x去掉k个a[n]),即成立。

  但是这样取模会出现正负数之间取模、和模0的问题,所以,这里采用a[j]和x同号则绝对值相减(差也取绝对值以保证为正数)取模a[n]的绝对值,异号则绝对值相加取模a[n]的绝对值,如果结果为零则成立。同时要判断k>=0是否成立,如果a[j]>x且a[n]>0或者a[j]<x且a[n]<0,此时k<0,不成立。对有无限个解的情况进行特判,即a[n]==0且存在前缀和a[j]==x,直接输出-1,如果a[n]==0且不存在a[j]==x,那么无解输出0。

AC代码

 

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 
 4 long long a[100001];
 5 
 6 long long absj(long long a,long long b){
 7     return abs(abs(a)-abs(b));
 8 }
 9 
10 long long absp(long long a,long long b){
11     return abs(abs(a)+abs(b));
12 }
13 
14 int main(){
15     
16     int t;
17     cin>>t;
18     
19     while(t--){
20         
21         long long n,x;
22         cin>>n>>x;
23         
24         string s;
25         cin>>s;
26         
27         s='%'+s;
28         
29         a[0]=0;
30         bool flag=0;
31         
32         for(int i=1;i<=n;i++){
33             
34             if(s[i]=='1'){
35                 a[i]=a[i-1]-1;
36             }
37             else{
38                 a[i]=a[i-1]+1;
39             }
40             
41             if(x==a[i]){
42                 flag=1;
43             }
44             
45         }
46         
47         if(a[n]==0){  
48             if(flag==1) cout<<-1<<endl;
49             else cout<<0<<endl;
50             continue;
51         }
52         
53         long long ans=0;
54         
55         if(x==0){ 
56             ans++;
57         }
58         
59         for(int i=1;i<=n;i++){
60             
61             if((a[i]>x&&a[n]>0)||(a[i]<x&&a[n]<0)){
62                 continue;
63             }
64             
65             if(a[i]*x>=0&&absj(a[i],x)%abs(a[n])==0){
66                 ans++;
67             }
68             if(a[i]*x<0&&absp(a[i],x)%abs(a[n])==0){
69                 ans++;
70             }
71             
72         }
73 
74         cout<<ans<<endl;
75 
76     }
77     
78     return 0;
79     
80 }

 

 (Orz,在线投诉老学姐压榨学弟写题!!!!)

 

题目链接:https://codeforces.com/contest/1295/problem/C

C题

题意:给出字符串s和字符串t,以及一个空字符串z,将s的某个子串加入z的末端计为一次操作,至少多少次操作可以使z和t相同?(无法完成则输出-1)

题解:

  思路:暴力贪心+优化!

  题目中问至少需要多少次操作,也就是尽可能少的分割t使其分割后的各部分为s的子串。

  最初的思路是,依次在s中查找t中的每个字符,如果出现t[i]==s[j],则i++(即从当前位置继续搜索t的下一位),将s中的字符全部访问一遍后计为一次操作。这样就是从t的头部依次寻找最长的s的子串。

  复杂度最大为1e10,显然TLE。

  优化:开一个vector<int> v[26]数组,把s中每个字母出现的位置依次存入数组,v[i]中存着对应字母出现的所有位置。遍历字符串t,查找t中字母在v[t[i]-'a']中大于前一个字母(t[i-1])出现的位置的最小值并更新当前位置,如果不存在这样的位置则操作数+1,并将当前位置重置为0。

  在vector数组中查找的过程中使用二分优化查找以减少时间复杂度。

AC代码

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 
 4 vector<int> v[26];
 5 
 6 void init(){
 7     
 8     for(int i=0;i<=25;i++){
 9         v[i].clear();
10     }
11     
12 }
13 
14 int main(){
15     
16     int t;
17     cin>>t;
18     while(t--){
19         
20         init();
21         
22         string s,t;
23         cin>>s>>t;
24         
25         int ls=s.length(),lt=t.length();
26         s='%'+s,t='%'+t;
27         
28         for(int i=1;i<=ls;i++){
29             v[s[i]-'a'].push_back(i);
30         }
31         
32         int l=1,r=1,ans=1;
33         bool ff=1;
34         
35         int M=0;
36         
37         while(l<=lt){
38                         
39             int p=t[l]-'a';
40             
41             if(!v[p].size()){
42                 ff=0;
43                 break;
44             }
45             
46             if(v[p][v[p].size()-1]<=M){
47                 ans++;
48                 M=0;
49                 continue;
50             }
51             
52             int ll=0,rr=v[p].size()-1;    
53             
54         /*    for(int j=0;j<v[p].size();j++){  //TLE 12
55                 if(v[p][j]>M){
56                     M=v[p][j];
57                     l++;
58                     break;
59                 }
60             }*/    
61                 
62             while(ll<rr){ //二分优化
63                 
64                 int mid=(ll+rr)>>1;
65                 
66                 if(v[p][mid]>M){
67                     rr=mid;
68                 }
69                 else{
70                     ll=mid+1;
71                 }
72                 
73             }
74             
75             M=v[p][ll],l++;
76             
77         }
78         
79         if(!ff){
80             cout<<-1<<endl;
81         }
82         else{
83             cout<<ans<<endl;
84         }
85         
86     } 
87     
88     return 0;
89     
90 }

 

  摸过的🐟,划过的水,早晚要还的~(暗示ljxfp赶紧来写题)

 

posted @ 2020-01-31 00:30  VioletOrz  阅读(154)  评论(0编辑  收藏  举报