Educational Codeforces Round 81 (Rated for Div. 2)A,B,C,D题解 比赛链接:https://codeforces.com/contest/1295
A.Display The Number(思维+构造) 题意:
思路: 如果想让构造一个最大的数,我们要使它的位数越多越好,而且使用最少的线段的数字是1(需要两根线段)。当线段的数量为偶数时我们把所有线段都用来构造1,此时构造的数字最大。当数量为奇数时,构造完全1的数字后还剩一根线段,我们肯定要把这根线段用在构造的数字最高位,将1变为7,此时便构造出了最大的数字。
Code: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 #include <bits/stdc++.h> using namespace std ;typedef long long ll;int ans[100000 +7 ];int main () { int T; scanf ("%d" ,&T); while (T--) { int n; scanf ("%d" ,&n); if (n==3 ) {printf ("7\n" );continue ;} int dig=n/2 ; int lef=n%2 ; for (int i=1 ;i<=dig;i++) { ans[i]=1 ; } if (lef==1 ) ans[1 ]=7 ; for (int i=1 ;i<=dig;i++) printf ("%d" ,ans[i]); printf ("\n" ); } return 0 ; }
B. Infinite Prefixes(思维+构造转化) 题意:
思路: 对于每一个前缀,我们用ans[i]记录前i个字符的$cnt0-cnt1$的值,同时$k=整个串的cnt0-cnt1=ans[last]$。
那么比如,$ans[z]=h$,若前面有n个串的$cnt0-cnt1$=$x-h$,那么$x-h+ans[z]=x$,即可以找出一个值为x的串。
即寻找$n*k=x-h=x-ans[z]$符合这个式子的z和n的对数。
注意:空串也算答案!
Code: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 #include <bits/stdc++.h> using namespace std ;typedef long long ll;int ans[100000 +7 ];char s[100000 +5 ];int main () { int T; cin >>T; while (T--) { int n,x,cnt0=0 ,cnt1=0 ; scanf ("%d%d" ,&n,&x); scanf ("%s" ,s); for (int i=0 ;i<n;i++) { if (s[i]-'0' ==0 ) cnt0++; else cnt1++; ans[i]=cnt0-cnt1; } int k=cnt0-cnt1,flag=1 ,fin=0 ; if (k==0 ) { for (int i=0 ;i<n;i++) { if (ans[i]==x) {flag=0 ;break ;} } } if (flag==0 ) { printf ("-1\n" ); continue ; } if (flag&&k==0 ) {printf ("0\n" );continue ;} for (int i=0 ;i<n;i++) { if ((x-ans[i])%k==0 &&(x-ans[i])/k>=0 ) fin++; } if (x==0 ) fin++; printf ("%d\n" ,fin); } return 0 ; }
C-Obtain The String(二分+贪心) 题意:
思路: $pos[x][y]$代表第y个字母x的位置 这个位置有单调性是单增的,我们对t串的每一个字符在s串中进行查询,比如查询字母a,通过二分$dig[a-‘0’][ t ]$对t二分出第一个大于当前s串指针的位置,如果二分不出来就把指针移到s串开头,从头开始二分,同时ans++。
Code: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 #include <bits/stdc++.h> using namespace std ;typedef long long ll;char t[100000 +5 ];char s[100000 +5 ];int pos[27 ][100000 +5 ];int main () { int T; cin >>T; while (T--) { scanf ("%s" ,s); scanf ("%s" ,t); int ed[27 ]; memset (ed,-1 ,sizeof ed); int lens=strlen (s); for (int i=0 ;i<lens;i++) { int tep=s[i]-'a' ; ed[tep]++; pos[tep][ed[tep]]=i; } int lent=strlen (t),ans=1 ,now=-1 ,flag=1 ; for (int i=0 ;i<lent;i++) { int tep=t[i]-'a' ; int l=0 ,r=ed[tep]; if (r==-1 ) {printf ("-1\n" );flag=0 ;break ;} while (l<r) { int mid=(l+r)>>1 ; if (pos[tep][mid]>now) r=mid; else l=mid+1 ; } if (l==ed[tep]&&pos[tep][l]<=now) { now=-1 ; ans++; i--; continue ; } else now=pos[tep][l]; } if (flag) printf ("%d\n" ,ans); } return 0 ; }
D-Same GCDs(辗转相除法转化+phi) 题意:
思路:
Code: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 #include <bits/stdc++.h> using namespace std ;typedef long long ll;ll phi (ll n) { ll result = n; for (ll p = 2 ; p * p <= n; ++p) { if (n % p == 0 ) { while (n % p == 0 ) n /= p; result -= result / p; } } if (n > 1 ) result -= result / n; return result; }int main () { ll t; cin >> t; while (t--) { ll a, m; cin >> a >> m; ll g = __gcd(a, m); m /= g; cout << phi(m) << endl ; } return 0 ; }