ural 1007


Time Limit:2000MS     Memory Limit:16384KB     64bit IO Format:%I64d & %I64u

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:
  1. Any (but only one) symbol 0 is replaced by 1.
  2. Any (but only one) symbol is removed.
  3. 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;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值