Codeforces Round #769 (Div. 2) A B C D

Codeforces Round #769 (Div. 2) A B C D

  • 新年后的康复训练,把近几场vp了,题能补的补补掉。

A ABC(800)

思路: 明显 0 0 0 1 1 1两者中其中一者出现次数大于等于 2 2 2就一定无法重新排列成长度最大为 1 1 1的回文。

  • 参考代码:
#include<bits/stdc++.h>
using namespace std;
#define mp make_pair
#define int long long 
#define re register int
#define pb emplace_back
#define lowbit(x) (x&-x)
#define fer(i,a,b) for(re i = a ; i <= b ; i ++)
#define der(i,a,b) for(re i = a ; i >= b ; i --)
#define snow ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
int gcd(int a,int b){return b?gcd(b,a%b):a;}
int lcm(int a,int b){return a*b/gcd(a,b);}
typedef pair<int,int>PII;
typedef pair<int,string>PIS;
signed main(){
    int t;
    cin>>t;
    while(t--){
        int n;
        cin>>n;
        string s;
        cin>>s;
        int sum1,sum2;
        sum1=sum2=0;
        for(int i=0;i<s.size();i++)if(s[i]=='0')sum1++;
        else sum2++;
        if(sum1>=2||sum2>=2)cout<<"NO"<<endl;
        else cout<<"YES"<<endl;
    }
    return 0;
}

B Roof Construction(1000)

思路: 因为要求所以相邻数的 ⊕ ⊕ 的最大值最小。那么在二进制形式下可以发现,最大的不超过 n n n 2 x 2^x 2x一定要和 0 0 0相邻才能使得 ⊕ ⊕ 最小,因为剩余的 2 x + 1 2^x+1 2x+1~ n n n之间的数可以通过相邻的放置使得 ⊕ ⊕ 永远小于 2 x 2^x 2x 0 0 0 ⊕ ⊕ 值。

  • 参考代码:
#include<bits/stdc++.h>
using namespace std;
#define mp make_pair
#define int long long 
#define re register int
#define pb emplace_back
#define lowbit(x) (x&-x)
#define fer(i,a,b) for(re i = a ; i <= b ; i ++)
#define der(i,a,b) for(re i = a ; i >= b ; i --)
#define snow ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
int gcd(int a,int b){return b?gcd(b,a%b):a;}
int lcm(int a,int b){return a*b/gcd(a,b);}
typedef pair<int,int>PII;
typedef pair<int,string>PIS;
signed main(){
    int t;
    cin>>t;
    while(t--){
        int n;
        cin>>n;
        int x=n-1;
        int sum=1;
        while(sum<x){
            sum*=2;
        }
        if(sum>x)sum/=2;
        for(int i=n-1;i>=sum;i--)cout<<i<<' ';
        for(int i=0;i<=sum-1;i++)cout<<i<<' ';
        cout<<endl;
    }
    return 0;
}

C Strange Test(1600)

  • Tip:brute force、math

思路: 对于 m e t h o n 3 methon3 methon3有两种选择,一种是不使用 m e t h o n 3 methon3 methon3那么最少的操作次数显然是 b − a b-a ba,一种是使用 m e t h o n 3 methon3 methon3且最多只会使用一次,因为 a ∣ b a|b ab ≥ \ge b b b,在操作一次 m e t h o n 3 methon3 methon3之后我们剩下的只需操作 m e t h o n 2 methon2 methon2即可。然后通过推公式可得:假设 c c c ≥ \ge a a a d d d ≥ \ge b b b c c c d d d a a a b b b通过操作 m e t h o n 1 methon1 methon1 m e t h o n 2 methon2 methon2转变而来,那么我们可得公式: s u m = c − a + d − b + c ∣ d − d + 1 = c + c ∣ d + ( 1 − a − b ) sum=c-a+d-b+c|d-d+1=c+c|d+(1-a-b) sum=ca+db+cdd+1=c+cd+(1ab),由于 ( 1 − a − b ) (1-a-b) (1ab) c o n s t a n t constant constant所以我们最终的目标值是使 c + c ∣ d c+c|d c+cd最小, c c c的迭代区间为 [ a , b − 1 ] [a,b-1] [a,b1],因为 c c c ≥ \ge b b b的话还不如 b − a b-a ba来的更优。由于 a l l all all b b b ≤ \le 1 e 6 1e6 1e6所以跑暴力时间复杂度为 O ( b ) O(b) O(b)可以接受。然后每次的 c c c是确定的,为了 c ∣ d c|d cd尽可能小,所以我们构造一个 d d d即可( d d d ≥ \ge b b b)。
1 : I f 1:If 1:If c u r r e n t current current b i t bit bit o f of of c c c i s is is 0 0 0 a n d and and b b b i s is is 1 , 1, 1, s e t set set t h e the the c u r r e n t current current b i t bit bit o f of of d d d t o to to 1. 1. 1.
2 : I f 2:If 2:If c u r r e n t current current b i t bit bit o f of of c c c i s is is 0 0 0 a n d and and b b b i s is is 0 , 0, 0, s e t set set t h e the the c u r r e n t current current b i t bit bit o f of of d d d t o to to 0. 0. 0.
3 : I f 3:If 3:If c u r r e n t current current b i t bit bit o f of of c c c i s is is 1 1 1 a n d and and b b b i s is is 1 , 1, 1, s e t set set t h e the the c u r r e n t current current b i t bit bit o f of of d d d t o to to 1. 1. 1.
4 : I f 4:If 4:If c u r r e n t current current b i t bit bit o f of of c c c i s is is 1 1 1 a n d and and b b b i s is is 0 , 0, 0, s e t set set t h e the the c u r r e n t current current b i t bit bit o f of of d d d t o to to 1 1 1 a n d and and s t o p . stop. stop.

  • 参考代码:
#include<bits/stdc++.h>
using namespace std;
#define mp make_pair
#define int long long 
#define re register int
#define pb emplace_back
#define lowbit(x) (x&-x)
#define fer(i,a,b) for(re i = a ; i <= b ; i ++)
#define der(i,a,b) for(re i = a ; i >= b ; i --)
#define snow ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
int gcd(int a,int b){return b?gcd(b,a%b):a;}
int lcm(int a,int b){return a*b/gcd(a,b);}
typedef pair<int,int>PII;
typedef pair<int,string>PIS;
signed main(){
    int t;
    cin>>t;
    while(t--){
        int a,b;
        cin>>a>>b;
        int ans=b-a;
        for(int c=a;c<b;c++){
            int d=0;
            for(int j=31;j>=0;j--){
                if(b>>j&1){
                    d+=1<<j;
                }
                else{
                    if(c>>j&1){
                        d+=1<<j;
                        break;
                    }
                }
            }
            ans=min(ans,c+(c|d)+1-a-b);
        }
        cout<<ans<<endl;
    }
    return 0;
}

D New Year Concert(2000)

  • Tip: greedy、math、two pointers、sparse table

思路: 很不错的一道题,让我捡起了ST表,之前在 A c w i n g Acwing Acwing学过倍增。但是对于ST表建立区间查询的板子还没有学习,这次给一起学了。感觉这道题综合了很多东西。首先如果一个区间内所有数的 g c d gcd gcd等于该区间 r − l + 1 r-l+1 rl+1那么这个区间是个 b a d bad bad的区间,我们的任务就是找到所有的 b a d bad bad区间,通过最小的更改使得所有的 b a d bad bad的区间消失。因为 a a a的范围非常大,我们可以找一个很大的质数使得该原本 b a d bad bad的区间变成 g o o d good good的区间。然后我们需要在区间内选择一个数将其变成该很大的质数,显然区间的最后一个数是最优的(贪心),因为可能后续有很多的 b a d bad bad区间的 l l l ≤ \le 当前区间的 r r r,那么更改最后一个,我们可以使得后续的那些 l l l ≤ \le 当前区间的 r r r的区间全部变成 g o o d good good区间,这会使得我们最终的操作次数最少。然后区间查询 g c d gcd gcd就套用 S T ST ST表的板子。然后进行处理,有一个很强的性质, g c d gcd gcd会随着区间的变大越来越小, r − l + 1 r-l+1 rl+1会越来越大。而我们题目要求最终输出是随着 r r r变大的在线区间内最小的更改次数。那么随着 r r r变大如果 g c d ( gcd( gcd(l − - r ) ) )已经 < < < r − l + 1 r-l+1 rl+1那么永远无法再找到 g c d ( gcd( gcd(l − - r ) ) ) = = == == < < < r − l + 1 r-l+1 rl+1因为前者会越来越小后者会越来越大。我们我们如果碰到 g c d ( gcd( gcd(l − - r ) ) ) < < < r − l + 1 r-l+1 rl+1的情况我们需要将 l + + l++ l++直到 g c d ( gcd( gcd(l − - r ) ) ) ≥ \ge r − l + 1 r-l+1 rl+1

  • 参考代码:
#include<bits/stdc++.h>
using namespace std;
#define mp make_pair
#define int long long 
#define re register int
#define pb emplace_back
#define lowbit(x) (x&-x)
#define fer(i,a,b) for(re i = a ; i <= b ; i ++)
#define der(i,a,b) for(re i = a ; i >= b ; i --)
#define snow ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
int gcd(int a,int b){return b?gcd(b,a%b):a;}
int lcm(int a,int b){return a*b/gcd(a,b);}
typedef pair<int,int>PII;
typedef pair<int,string>PIS;
int n;
const int N=2e5+10;
int a[N];
int st[N][20];
void make_st(){
    int k=__lg(n);
    for(int i=1;i<=n;i++)st[i][0]=a[i];
    for(int i=1;i<=k;i++){
        for(int j=1;j+(1<<i)-1<=n;j++){
            st[j][i]=gcd(st[j][i-1],st[j+(1<<(i-1))][i-1]);
        }
    }
}
int query(int l,int r){
    int k=__lg(r-l+1);
    return gcd(st[l][k],st[r-(1<<k)+1][k]);
}
signed main(){
    snow;
    cin>>n;
    for(int i=1;i<=n;i++)cin>>a[i];
    make_st();
    int ans=-1;
    int res=0;
    int l=1;
    for(int r=1;r<=n;r++){
        while(l<r&&query(l,r)<r-l+1)l++;
        if(query(l,r)==r-l+1){
            if(l>ans){
                ans=r;
                res++;
            }
        }
        cout<<res<<' ';
    }
    cout<<endl;
    return 0;
}

收获:1:ST板子、2: l o g log log 2 2 2为底的数 n n n可以直接调用__ l g ( n ) lg(n) lg(n)

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值