Codeforces Global Round 18 C. Menorah

Codeforces Global Round 18 C. Menorah

最近期末周,补个C复习期末去了,写一下我对这题的理解和证明。只看代码的话还是满简单的,没有题目经验所以推出这道题对我来说还是满困难的。

思路+证明: 一共有 4 4 4个状态: 00 、 01 、 10 、 11 。 00、01、10、11。 00011011根据题目的意思,首先至少有一支点燃的蜡烛才能进行操作,并且每次操作点燃的蜡烛状态不改变,其他状态如果是 0 0 0变成 1 1 1否则变成 0 0 0。那我们开始考虑 s t r i n g string string A A A 如何变成 s t r i n g string string B B B。首先有 1 1 1个性质, 1 1 1个数操作最多不超过 1 1 1次,因为如果操作 2 2 2次和没操作是一样的,而我们求的是最小操作次数。那么 11 11 11 00 00 00最后要想保持不变,那么被改变的次数一定是偶数次,而如果 01 01 01 10 10 10最后肯定是要变成 00 00 00 11 ( 题 目 要 求 ) 11(题目要求) 11()那么肯定要被改变奇数次。那这时候题目就转变成了如何让 11 、 00 11、00 1100改变偶数次, 10 、 01 10、01 1001改变奇数次。 因为上面说过一个点燃的蜡烛操作的时候自身是不会改变的,那么我们可以通过2次操作使得一组 01 、 10 01、10 0110变成 11 、 00 11、00 1100,例如:
10 10 10 11 11 11 01 01 01
01 01 01 01 01 01 01 01 01
我们可以发现,要想通过操作 01 、 10 01、10 0110最终让 s t r i n g string string A A A 变成 s t r i n g string string B B B那么上面的 1 1 1的个数和下面的 1 1 1的个数一定要相等,才能通过移动上面 1 1 1的位置使得上面和下面是一样的,换句话说就是 01 01 01的数量和 10 10 10的数量要相等。否则如果 01 01 01 10 10 10数量不相等那我们还可以判断是否其满足第二种条件,是否能够通过被动改变奇数次使得上面变成下面,那么也就是 11 、 00 11、00 1100部分操作奇数次被动改变 01 、 10 01、10 0110部分。那么最终 11 、 00 11、00 1100部分需要改变偶数次,所以每个 11 、 00 11、00 1100部分都要操作一次。并且 11 11 11的数量+ 00 00 00的数量一定是奇数个而且要满足 11 11 11部分一次操作后其余的 11 、 00 11、00 1100部分变成 10 、 01 10、01 1001数量相等,这前提需要满足一种性质: 11 11 11的数量- 00 00 00的数量为 1 1 1,然后就转变成第一种情况。如果都不满足那么输出 − 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;
string s1,s2;
int a,b,c,d;
int val;
signed main(){
    int t;
    cin>>t;
    while(t--){
        int n;
        cin>>n;
        cin>>s1>>s2;
        a=b=c=d=0;
        for(int i=0;i<s1.size();i++){
            if(s1[i]=='0'){
                if(s2[i]=='0')a++;
                else b++;
            }
            else{
                if(s2[i]=='0')c++;
                else d++;
            }
        }
        if(s1==s2){
            cout<<0<<endl;
            continue;
        }
        val=INT_MAX;
        if(b==c){
            val=min(val,b+c);
        }
        if(d-a==1){
            val=min(val,d+a);
        }
        cout<<(val==INT_MAX?-1:val)<<endl;
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值