Codeforces Global Round 18 C. Menorah
最近期末周,补个C复习期末去了,写一下我对这题的理解和证明。只看代码的话还是满简单的,没有题目经验所以推出这道题对我来说还是满困难的。
思路+证明: 一共有 4 4 4个状态: 00 、 01 、 10 、 11 。 00、01、10、11。 00、01、10、11。根据题目的意思,首先至少有一支点燃的蜡烛才能进行操作,并且每次操作点燃的蜡烛状态不改变,其他状态如果是 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 11、00改变偶数次, 10 、 01 10、01 10、01改变奇数次。 因为上面说过一个点燃的蜡烛操作的时候自身是不会改变的,那么我们可以通过2次操作使得一组 01 、 10 01、10 01、10变成 11 、 00 11、00 11、00,例如:
10 10 10 11 11 11 01 01 01
01 01 01 01 01 01 01 01 01
我们可以发现,要想通过操作 01 、 10 01、10 01、10最终让 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 11、00部分操作奇数次被动改变 01 、 10 01、10 01、10部分。那么最终 11 、 00 11、00 11、00部分需要改变偶数次,所以每个 11 、 00 11、00 11、00部分都要操作一次。并且 11 11 11的数量+ 00 00 00的数量一定是奇数个而且要满足 11 11 11部分一次操作后其余的 11 、 00 11、00 11、00部分变成 10 、 01 10、01 10、01数量相等,这前提需要满足一种性质: 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;
}