Codeforces Round 1030 (Div. 2)(A~C)

A.Equal Subsequences

给定n,k,要求构造出一个只包含0和1的字符串,且字符串中101子序列和010子序列有相同的个数。

那么11111101000000,即取出01,然后左边有多少个1,就有多少个101子序列,右边有多少个0,就有多少个010子序列,那么再将多余的0和1放入字符串内即可完成构造。

单独考虑多余1的位置,只有5个可能位置,依次试过之后,可以发现11111(多余0)01(多余1)00000是符合要求的构造方法,其中多余0和多余1只会有一个有内容。

 1 #include <iostream>
 2 #include <cstring>
 3 #include <algorithm>
 4 using namespace std;
 5  
 6 int main()
 7 {
 8     int t;
 9     cin>>t;
10     while(t--){
11         int n,k;
12         cin>>n>>k;
13         if(n==k){
14             for(int i=0;i<n;i++)
15                 cout<<1;
16             cout<<endl;
17             continue;
18         }
19         if(k==0){
20             for(int i=0;i<n;i++)
21                 cout<<0;
22             cout<<endl;
23             continue;
24         }
25             
26         int cnt0=n-k,cnt1=k;
27         string res="01";
28         cnt0--;
29         cnt1--;
30         int t=min(cnt0,cnt1);
31     if(cnt1>cnt0)
32             for(int i=0;i<cnt1-cnt0;i++)
33                 res=res+"1";
34         else
35             for(int i=0;i<cnt0-cnt1;i++)
36                 res="0"+res;
37         for(int i=0;i<t;i++)
38             res="1"+res+"0";
39         cout<<res<<endl;
40     }
41     return 0;
42 }

B.Make It Permutation

给定一个大小为n*n的第j列元素全为j的矩阵,每次操作能选择一行的一个子串进行反转,要求我们对原矩阵进行不超过2*n次操作,使得操作后的矩阵每一行都为1~n的一个排列,输出操作序列。

可以发现,对于一个序列1 2 3 ... n,整体往后移1位的操作需要三个,即1 n,1 1,2 n,整体向后移2位的操作为1 n,1 2,3 n,即首先整体反转,再反转1~k,再反转k+1~n,k为需要后移几位。按照如此操作,需要3*n-3个操作(第一行不需要操作),与题目要求不符。

可以发现上述有一个同样的操作,即将序列整体反转,那么我们将第一行反转,其他的n-1行则为第一行整体反转之后的结果,然后再按照原来的操作即可,按照如此操作,需要2*n-1个操作。

 1 #include <iostream>
 2 #include <cstring>
 3 #include <algorithm>
 4 using namespace std;
 5  
 6 int main()
 7 {
 8     int t;
 9     cin>>t;
10     while(t--){
11         int n;
12         cin>>n;
13         cout<<2*n-1<<endl;
14         cout<<1<<" "<<1<<" "<<n<<endl; 
15         for(int i=2;i<=n;i++){
16             cout<<i<<" "<<1<<" "<<i-1<<endl;
17             cout<<i<<" "<<i<<" "<<n<<endl;
18         }
19     }
20     return 0;
21 }

C.Make It Beautiful

定义一个元素的二进制表示中1的个数之和为其beauty值,给定一个包含n个数的数组,以及k次操作,每次操作可选择数组中一个数+1,问整个数组的beauty值最大为多少。

k的值为1e18,对于数组中每个数,只有其二进制表示中为0的位置才能加上之后使得1的数目+1,而又有2^60>1e18,所以long long的63位足够覆盖所有1e18的范围。

 1 #include <iostream>
 2 #include <cstring>
 3 #include <algorithm>
 4 #include <vector>
 5 using namespace std;
 6 typedef long long LL;
 7 int main()
 8 {
 9     int t;
10     cin>>t;
11     while(t--){
12         LL n,k;
13         vector<LL> v;
14         cin>>n>>k;
15         LL res=0;
16         for(int i=0;i<n;i++){
17             LL x;
18             cin>>x;
19             for(int j=0;j<=62;j++){
20                 if((x>>j)&1) res++;
21                 else{
22                     v.push_back(1ll<<j);
23                 }
24             }
25         }
26         sort(v.begin(),v.end());
27         
28         for(int i=0;i<v.size();i++){
29 //            cout<<v[i]<<" ";
30             if(k>=v[i]){
31                 res++;
32                 k-=v[i];
33             }else
34                 break;
35         }
36 //        cout<<endl; 
37         cout<<res<<endl;
38     }
39     return 0;
40 }

 

posted on 2025-06-13 08:33  greenofyu  阅读(47)  评论(0)    收藏  举报