<span>Codeforces Round #634 (Div. 3)</span>
D题想复杂了,花了好多时间,感觉也没时间看F了,就来写个题解蹭蹭访问量把^_^
传送门:1335 A. Candies and Two Sisters
题意:你要把n个糖果分给两个人,两个人的糖果数不能相等,问你有几种分法。
题解:就是(n-1)/2
1 #include<bits/stdc++.h> 2 #define ll long long 3 using namespace std; 4 5 int main() 6 { 7 ios::sync_with_stdio(false); 8 cin.tie(0); 9 cout.tie(0); 10 ll n; 11 ll t; 12 cin>>t; 13 while(t--){ 14 cin>>n; 15 cout<<(n-1)/2<<endl; 16 } 17 return 0; 18 }
传送门:1335 B. Construct the String
题意:给你三个数 n, a , b , 构造一个长度为n的字符串,每个长度为a的子串必须有b个不同的字母。
题解:前b个字符从 'a' 到 'a' + b - 1,然后从第b+1个开始,每个字符和第 i - b 个相等。
1 #include<bits/stdc++.h> 2 #define ll long long 3 using namespace std; 4 5 char s[100100]; 6 7 int main() 8 { 9 ios::sync_with_stdio(false); 10 cin.tie(0); 11 cout.tie(0); 12 int t; 13 cin>>t; 14 while(t--){ 15 int n,a,b; 16 cin>>n>>a>>b; 17 for(int i=0;i<b;i++) 18 s[i]='a'+i; 19 for(int i=b;i<n;i++){ 20 s[i]=s[i-b]; 21 } 22 s[n]='\0'; 23 cout<<s<<endl; 24 } 25 return 0; 26 }
传送门:1335 C. Two Teams Composing
题意:用给定的数列构造两个长度相等数列,一个里边全是相等的数,另一个全是不同的数,问构造的数列最大的长度。
题解:先找出个数最多的用ans记录,然后找有多少个不同的数字用p记录,如果ans>p-1(除去ans记录的那个数外的个数), ans--, 否则 p--, ans和p的最小值即为答案。
1 #include<bits/stdc++.h> 2 #define ll long long 3 using namespace std; 4 5 int a[200100]; 6 7 int main() 8 { 9 ios::sync_with_stdio(false); 10 cin.tie(0); 11 cout.tie(0); 12 int t; 13 cin>>t; 14 while(t--){ 15 int n; 16 cin>>n; 17 for(int i=0;i<n;i++) cin>>a[i]; 18 sort(a,a+n); 19 if(n==1) cout<<0<<endl; 20 else { 21 int ans=1,cnt=1,p=1; 22 for(int i=1;i<n;i++){ 23 if(a[i]==a[i-1]) cnt++; 24 else{ 25 p++; 26 ans=max(ans,cnt); 27 cnt=1; 28 } 29 } 30 ans=max(ans,cnt); 31 if(ans>p-1) ans--; 32 else p--; 33 cout<<min(p,ans)<<endl; 34 } 35 } 36 return 0; 37 }
题意:给你一个9*9数独,最多9次操作改一个格子的值,输出新的数独,要求每行,每列,每个加粗黑框的小矩阵至少有两个一样的数。
题解:日常读错题 按照题目的改就好了,我是这么操作的。其实只要每次选行,列,格都没被选过的改就行了。
1 #include<bits/stdc++.h> 2 #define ll long long 3 using namespace std; 4 5 char a[20][20]; 6 7 int main() 8 { 9 ios::sync_with_stdio(false); 10 cin.tie(0); 11 cout.tie(0); 12 int t; 13 cin>>t; 14 while(t--){ 15 for(int i=1;i<=9;i++) 16 cin>>a[i]+1; 17 a[2][2]=a[2][1]; 18 a[1][7]=a[1][6]; 19 a[3][6]=a[4][6]; 20 a[4][9]=a[3][9]; 21 a[5][3]=a[5][4]; 22 a[6][5]=a[7][5]; 23 a[7][8]=a[7][7]; 24 a[8][1]=a[8][2]; 25 a[9][4]=a[9][3]; 26 for(int i=1;i<=9;i++){ 27 cout<<a[i]+1<<endl; 28 } 29 } 30 return 0; 31 }
传送门:1335 E1. Three Blocks Palindrome (easy version)
题意:给你一个数列,你可以删除任意的数得到一个新数列,使得新数列是最长的回文串。回文串要前后两部分完全一样,中间部分完全一样,也就是前后都是同一个数,中间都是另一个数。
题解:本来想暴力枚举中间段的起始位置和终点位置,然后感觉会t,突然灵机一动,想到一个绝妙的办法。应该是o(nlogn)吧。不太会算,,
先二维数组记录到每个位置时26个数字出现了几次。然后枚举26个数,再枚举第一段的长度 j ,二分查找最左边第 j 次出现这个数的位置记为 l,二分查找最右边第 j 次出现这个数的位置记为 r,然后枚举这26个数比较每个 l+1 到 r-1出现的次数,ans记录次数+前后两部分的长度 j 的最大值。
1 #include<bits/stdc++.h> 2 #define ll long long 3 using namespace std; 4 5 int a[2010]; 6 int b[30][2010]; 7 8 int main() 9 { 10 ios::sync_with_stdio(false); 11 cin.tie(0); 12 cout.tie(0); 13 int t; 14 cin>>t; 15 while(t--){ 16 int n; 17 cin>>n; 18 for(int i=1;i<=n;i++) cin>>a[i]; 19 for(int i=1;i<=26;i++) b[i][0]=0; 20 for(int i=1;i<=n;i++){ 21 for(int j=1;j<=26;j++){ 22 if(a[i]==j) b[j][i]=b[j][i-1]+1; 23 else b[j][i]=b[j][i-1]; 24 } 25 } 26 int ans=1; 27 for(int i=1;i<=26;i++){ //枚举26个数 28 for(int j=1;j<=b[i][n]/2;j++){ //枚举左右各有几个该数 29 int cnt=j*2; 30 int l=lower_bound(b[i],b[i]+n,j)-b[i]; //二分查找最左边第j次出现这个数的位置 31 int r=lower_bound(b[i],b[i]+n,b[i][n]-j+1)-b[i]; //二分查找最右边第j次出现这个数的位置 32 for(int k=1;k<=26;k++){ //枚举中间的数字; 33 ans=max(ans,cnt+b[k][r-1]-b[k][l]); 34 } 35 } 36 } 37 cout<<ans<<endl; 38 } 39 return 0; 40 }
传送门:1335 E2. Three Blocks Palindrome (hard version)
题解:和E1做法一样,数组大小和枚举的数字个数变大了而已。(常数大到感觉会t ...)
1 #include<bits/stdc++.h> 2 #define ll long long 3 using namespace std; 4 5 int a[200010]; 6 int b[210][200010]; 7 8 int main() 9 { 10 ios::sync_with_stdio(false); 11 cin.tie(0); 12 cout.tie(0); 13 int t; 14 cin>>t; 15 while(t--){ 16 int n; 17 cin>>n; 18 for(int i=1;i<=n;i++) cin>>a[i]; 19 for(int i=1;i<=200;i++) b[i][0]=0; 20 for(int i=1;i<=n;i++){ 21 for(int j=1;j<=200;j++){ 22 if(a[i]==j) b[j][i]=b[j][i-1]+1; 23 else b[j][i]=b[j][i-1]; 24 } 25 } 26 int ans=1; 27 for(int i=1;i<=200;i++){ //枚举26个数 28 for(int j=1;j<=b[i][n]/2;j++){ //枚举左右各有几个该数 29 int cnt=j*2; 30 int l=lower_bound(b[i],b[i]+n,j)-b[i]; //二分查找最左边第j次出现这个数的位置 31 int r=lower_bound(b[i],b[i]+n,b[i][n]-j+1)-b[i]; //二分查找最右边第j次出现这个数的位置 32 for(int k=1;k<=200;k++){ //枚举中间的数字; 33 ans=max(ans,cnt+b[k][r-1]-b[k][l]); 34 } 35 } 36 } 37 cout<<ans<<endl; 38 } 39 return 0; 40 }