不打算把所有的新生赛题目都写成博客上的,感觉这道写了挺久,所以记一下,哈哈哈
首先,题目如下:
Chocolate (10分)
C时间限制:1000 毫秒 | C内存限制:3000 Kb
题目内容:
还是小W,他挑选完给小H的完美巧克力之后自己吃完了剩下的巧克力,他发现:
巧克力是世界上最好吃的东西!
所以他火速下单又购买了一批巧克力。
这次的巧克力中有黑白两种巧克力豆,小W仔细观察,认真分析,取出两种巧克力,摆成一排:你看这个巧克力豆又大又圆,多像二进制串啊!
所以他决定用黑白巧克力豆来出这道题。
现在抽象此问题,给定p,q,给出长度为p的二进制串,将此二进制串向后移动一次,共移动q-1次,可以算出p+q-1位的每一位异或值,所谓异或即是00=0,11=0,0^1=1,即相同取零, 相异取1,当p = 6, q = 3时
101010
101010
101010
11010110
即结果为11010110, 现已知结果, 求初始的二进制串
输入描述
第一行两个正整数
第二行(p + q - 1)位二进制串
数据范围:
0<m<=n<=1000000
1<=n+m-1<=1000000
输出描述
输出长为p的二进制串
输入样例
6 3
11010110
输出样例
101010
然后开始解题思路:
因为此题需要用到异或,所以我们先来了解一下异或是什么(下图皆源自百度百科)
然后利用上图中第五条运算法则来推算一遍此题的规律
设数组a[1000000]中存的是结果数字串11010110
数组b[1000000]中存的是原数字串101010
然后我们来推算
101010
101010
101010
11010110
当i<q时
a[0]=b[0]; b[0]=a[0];
a[1]=b[1] ^ b[0]; b[1]=a[1]^a[0];
a[2]=b[0] ^ b[1] ^ b[2]; b[2]=a[2] ^ a[1];
所以在i<q时,b[i]=a[i]^a[i-1];
当q>=i>=p时
a[3]=b[1]^ b[2]^ b[3]; b[3]=a[3] ^ a[2] ^a[0] (a[0]=b[0]);
a[4]=b[2]^ b[3]^ b[4]; b[4]=a[4]^ a[3]^ a[0]^a[1] (a[0] ^a[1]=b[1]);
a[5]=b[3] ^b[4] ^b[5]; b[5]=a[5] ^a[4] ^a[2] ^a[1] (a[2] ^ a[1]=b[2]);
a[6]=b[4]^ b[5] ^b[6]; b[6]=a[6] ^a[5] ^a[3] ^a[2] ^a[0] (a[3] ^ a[2] ^a[0]=b[3])
所以在q>=i>=p时,b[i]=a[i]^ a[i-1]^ b[i-q];
最终代码如下
#include<stdio.h>
char a[1000005];
int p,q,b[1000005];
int main()
{
int j=0,i;
scanf("%d%d",&p,&q);
scanf(" "); //刷新缓冲区;
gets(a);
b[j]=(a[0]=='1');//因为第一个数都是与0异或,任何数与0异或都为它本身
for(int i=1;i<p;i++)
{
j++;
if(i<q)
{
b[j]=(a[i]-'0')^(a[i-1]-'0');
}
else
{
b[j]=(a[i]-'0')^(a[i-1]-'0')^b[i-q];
}
}
for(int i=0;i<j+1;i++)
printf("%d",b[i]);
return 0;
}