Description
A transmitter sends over a noisy line some binary code words. The receiver on the other end uses special technique to recover the original words.
Every word originally consists of symbols 0 and 1. All words have the same length
N (4 ≤
N ≤ 1000). After traveling through the noisy line one (but no more) of the following modifications to a word may occur:
- Any (but only one) symbol 0 is replaced by 1.
- Any (but only one) symbol is removed.
- A symbol (0 or 1) is inserted at any position.
It is known that the original words all have the following property: the sum of positions where symbols 1 are located is a multiple of (
N+1) or equal to zero.
Input
Input contains number
N followed by received words. The words are delimited with line breaks. There will be no more than 2001 words. There is nothing else in the input data, except maybe for some extra spaces or line breaks.
Output
Your program should print to output the original sequence of words as they were transmitted. The words should be delimited by line breaks.
Sample Input
input | output |
---|---|
4 0000 011 1011 11011 | 0000 0110 1001 1111 |
题目大意:给你一个数字N,表示原码为N位数,然后再输入多个已经经过处理的二进制数;要你输出原码,原码要符合一个规则,原码中的1所在的位置和%(取余)(N+1)要等于0;例:1011,因为(1+3+4)%5!=0,所以它不是原码。
变化为三种:1.把任意一位(只能一位)0改为1;2.把任意的一位删除(仅限一位);3.添加一个数(仅限一个);(不变化也可以)
分析:用三个函数分别表示三种变化。简单题。(先附上自己写的代码,略烦;再附上优化版【看别人的】)
#include <stdio.h>
#include <string.h>
char a[2010];
int n;
void add(char str[])//添加一位数
{
int len=strlen(str);
int i;
int flag=0;
for(i=0;i<=len;i++)
{
int sum=0;
for(int j=0;j<i;j++)
{
if(str[j]=='1')
sum+=j+1;
}
for(int j=i;j<len;j++)
{
if(str[j]=='1')
sum+=j+2;//相当于每个数后移一位,所以+2
}
if(sum%(n+1)==0)
{
flag=1;
break;
}
if((sum+i+1)%(n+1)==0)
{
flag=2;
break;
}
}
for(int j=0;j<i;j++)//输出
{
printf("%c",str[j]);
}
if(flag==1)
printf("0");
else if(flag==2)
printf("1");
for(int j=i;j<len;j++)
{
printf("%c",str[j]);
}
printf("\n");
return;
}
void jian(char str[])//删除一位数
{
int len=strlen(str);
int sum,i;//i为删除的数的位置
for(i=0;i<len;i++)
{
sum=0;
for(int j=0;j<i;j++)
{
if(str[j]=='1')
sum+=j+1;
}
for(int j=i+1;j<len;j++)
{
if(str[j]=='1')
sum+=j;
}
if(sum%(n+1)==0)
{
break;
}
}
for(int j=0;j<i;j++)//输出
printf("%c",str[j]);
for(int j=i+1;j<len;j++)
printf("%c",str[j]);
printf("\n");
return;
}
void change(char str[])//改变一位数
{
int len=strlen(str);
int sum=0;
for(int i=0;i<len;i++)
{
if(str[i]=='1')
sum+=i+1;
}
if(sum%(n+1)==0)
printf("%s\n",str);
else
{
int sum1;
int k;
for(k=0;k<len;k++)
{
if(str[k]=='1')
{
sum1=sum-k-1;
if(sum1%(n+1)==0)
{
str[k]='0';//找到便推出
break;
}
}
}
printf("%s\n",str);
}
return;
}
int main()
{
scanf("%d",&n);
while(scanf("%s",a)!=EOF)
{
int len=strlen(a);
if(len<n)
{
add(a);
}
else if(len>n)
{
jian(a);
}
else
{
change(a);
}
}
return 0;
}
下面是参考的一个代码,速度快,并且简洁。
#include <stdio.h>
#include <string.h>
char a[1010];
int num[1010];
//num[i]数组储存该位置之后(包括自身的位置)1的总个数
int n,sum,len;
void add()//添加一个数
{
for(int i=0;i<=len;i++)
{
if((sum+num[i])%(n+1)==0)//+num[i]相当于每个数向后移了一位
{
for(int j=0;j<i;j++)//找到就输出
printf("%c",a[j]);
printf("0");
printf("%s\n",a+i);
return;
}
else if((sum+num[i]+i+1)%(n+1)==0)
{
for(int j=0;j<i;j++)
printf("%c",a[j]);
printf("1");
printf("%s\n",a+i);
return;
}
}
}
void jian()//删除一个数
{
for(int i=0;i<len;i++)
{
if(a[i]=='0')
{
if((sum-num[i+1])%(n+1)==0)//-num[i+1]相当于前移一位
{
for(int j=0;j<i;j++)
printf("%c",a[j]);
printf("%s\n",a+i+1);
return;
}
}
else
{
if((sum-num[i+1]-i-1)%(n+1)==0)
{
for(int j=0;j<i;j++)
printf("%c",a[j]);
printf("%s\n",a+i+1);
return;
}
}
}
}
void change()//改变一个数
{
for(int i=0;i<len;i++)
{
if(a[i]=='1')
{
if((sum-i-1)%(n+1)==0)
{
a[i]='0';
break;
}
}
}
printf("%s\n",a);
return;
}
int main()
{
scanf("%d",&n);
while(scanf("%s",a)!=EOF)
{
sum=0;
len=strlen(a);
memset(num,0,sizeof(num));
for(int i=0;i<len;i++)
{
if(a[i]=='1')
sum+=i+1;
}
for(int i=len-1;i>=0;i--)//存储num
{
num[i]=num[i+1];
if(a[i]=='1')
num[i]++;
}
if(len<n)
{
add();
}
else if(len>n)
{
jian();
}
else
{
if(sum%(n+1)==0)
printf("%s\n",a);
else
change();
}
}
return 0;
}