cdoj 1017 王之困惑

众所周知,绩点王(以下简称王)是集训队中的学神,因为他的绩点总是满的。

一天晚上,王做了一个奇奇怪怪的梦。在这个奇奇怪怪的梦里,绩点是以一串01串表示的。而王则拥有两种神奇的魔法可以改变自己的绩点。

魔法 1 :使用此魔法时,王可以去掉当前绩点的最左边的第一个数。

魔法 2 :使用此魔法时,王可以在当前绩点的最右边增加一个数 x 。其中,若当前绩点的01串中,1的个数为奇数,那么 x=1 ;若1的个数为偶数,那么 x=0

假设王的绩点以 A 串表示,王想得到的绩点以 B 串表示。王想知道,能否通过使用以上两种魔法,使得自己的绩点变为 B 。(魔法的使用次数不限)

Input

第一行输入一个 T ,表示测试数据组数。 T1000

每一组测试数据包括两行。

第一行包含一个01串,表示王的绩点 A

第二行包含一个01串,表示王希望得到的绩点 B

01串的长度均不超过 1000

Output

每组测试数据的输出包含一行,如果能,则输出YES,否则,输出NO

Sample input and output

Sample InputSample Output
2
01011
0110
0011
1110
YES
NO

Hint

第一组数据中,王可以先使用两次魔法 1 ,将绩点变为011,再使用一次魔法 2 ,将绩点变为0110

第二组数据中,王无法将绩点变为王想要的绩点。


解析

规律题。设A中1的个数为s1,B中1的个数为s2

发现规律:

规律一:当s1偶数时,就不能再向A加1进去了,当s1奇数时,可以再向A加一个1进去(又变成了偶数个1,不能再加)。

所以

1.当s1偶数时s2不能超过s1

2.当s1奇数时s2不能超过s1+1

规律二:通过变化,可以向两个1之间插任意个0

证明:1.有偶数个1在数列中时,可以把首位的1放到尾部去。所以对于偶数个1在数列中的数列可以随意地向两个1之间插数。

            2.有奇数个1在数列中时,在尾部添1,又变成了情况1,然后达到目标后再把多添的1在首位删去。


因为当A串中1的个数为偶数时,可以在A串尾部添加任意个0。当A串中1的个数为奇数时,可以在尾部添加1个1。(因为添加完之后,1的个数就会变成偶数)所以我们可以将A串奇数个1的情况转成偶数个1的情况(通过在尾部加1),而偶数个1的情况,我们则可以将头部的1移动到尾部,并且可以在相邻两个1之间放任意个0(先在尾部补0,再删去头部的1,并在尾部加1)。所以可以将通过转换得到所有的情况。
设A串和B串的1的个数分别为s1,s2。
若s1为奇数,那么s1+1>=s2则可行。
若s1为偶数,那么s1>=s2则可行。

#include<cstdio>
#include<cstring>

using namespace std;

#define LOCAL

int A,B;
char s[1100];

int count()
{
	int Lenth=strlen(s),q=0;
	for(int i=0;i<=Lenth;i++) if(s[i]=='1') q++;
	return q;
}

int main()
{
#ifdef LOCAL
	freopen("A.in","r",stdin);
#endif
	int T; scanf("%d",&T);
	for(int i=1;i<=T;i++)
	{
		scanf("%s",s);
		A=count();
		scanf("%s",s);
		B=count();
		if(A&1) printf("%s\n",A+1>=B?"YES":"NO");
		else printf("%s\n",A>=B?"YES":"NO");
	}

#ifdef LOCAL
	while(1);
#endif
	return 0;
}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值