1 条题解

  • 0
    @ 2025-8-24 21:40:37

    自动搬运

    查看原文

    来自洛谷,原作者为

    avatar jun头吉吉
    alive

    搬运于2025-08-24 21:40:37,当前版本为作者最后更新于2020-07-04 12:56:54,作者可能在搬运后再次修改,您可在原文处查看最新版

    自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多

    以下是正文


    一道简单的模拟题

    首先我们来看一下题面

    严格与图2中的0~9相符

    ??? 图呢

    黑人问号

    根据我们的生活经验,我们知道090\to 9应该是这么摆的:

    0~9

    首先我们发现,题目中不能移动构成运算符(+、-、=)的木棒 ,因此我们不管怎么移动数字的木棒,这个数的加、减和位数是不变的。我们如果把所有的数字都按照位数拆开来,以样例为例

    11+77=34
    

    变成

    1*10+1*1+7*10+7*1=3*10+4*1
    

    那么不管数字怎么变,它后面乘的多少是不会变的,因此我们可以提前处理好。然而在等号两边让我们看起来很不爽,反正符号不会变,我们可以通过初中知识移项将其全部移到一遍就ok了

    1*10+1*1+7*10+7*1-3*10-4*1=0
    

    那我们现在只需要通过更改上式中任意两个第一项使其成立就做完了

    我们知道n1000n\le 1000,因此我们完全可以枚举两个数,然后考虑移动火柴带来的情况,在判断是否成立

    由于我比较懒,用了一种常数较大的O(n2)O(n^2)算法,即选一个有火柴的地方,在选取一个没有火柴的地方,移动火柴,判断式子是否成立(其实这么做枚举了很多不必要的情况)

    对于一个数字,选择用状压去描述,如果有第ii根火柴,二进制下第ii位就是11,反之为00

    当对第ii根火柴进行更改时,就把数字2i\oplus2^i即可

    具体实现可以参考代码

    #include<bits/stdc++.h>
    char ch[2000];
    const int n[10]={0b1111011,//0
    				 0b1001000,//1
    				 0b0111101,//2
    				 0b1101101,//3
    				 0b1001110,//4
    				 0b1100111,//5
    				 0b1110111,//6
    				 0b1001001,//7
    				 0b1111111,//8
    				 0b1101111//9
    				 };
    struct num{//数字 
    	int val;//权值 
    	int des;//描述
    	/*
    	 _   1
    	|_|  2 3 4
    	|_|  5 6 7 
    	*/
    	/*                  7 6 5 4 3 2 1
    	1  4 7              1 0 0 1 0 0 0
    	2  1 3 4 5 6        0 1 1 1 1 0 1
    	3  1 3 4 6 7        1 1 0 1 1 0 1
    	4  2 3 4 7          1 0 0 1 1 1 0
    	5  1 2 3 6 7        1 1 0 0 1 1 1
    	6  1 2 3 5 6 7      1 1 1 0 1 1 1
    	7  1 4 7            1 0 0 1 0 0 1
    	8  1 2 3 4 5 6 7    1 1 1 1 1 1 1
    	9  1 2 3 4 6 7      1 1 0 1 1 1 1
    	0  1 2 4 5 6 7      1 1 1 1 0 1 1
    	*/
    	bool check(){//检验是否合法 
    	 	for(int i=0;i<10;i++)
    	 		if(val==n[i])
    	 			return true;
    	 	return false;
    	}
    	bool check(int w){//检验第w根是否存在 
    		if(val>>w&1!=0)return true;
    		return false; 
    	}
    	bool change(int w){//更改w根的位置 
    		val^=(1<<w);
    	}
    	int get(){
    		for(int i=0;i<10;i++)
    			if(val==n[i])
    				return i;
    	}
    	num(int _N=0,int Wi=0,int type=0){//_N表示数值  Wi表示位置 
    		val=n[_N];
    		des=type*pow(10,Wi); 
    	}
    }a[2000];
    bool check(num *t,int L){//检查 
    	int num=0;
    	for(int i=1;i<=L;i++){
    		if(!t[i].check())return false;
    		num+=t[i].des*t[i].get();
    	}
    	return num==0;
    }
    int tot=0;
    signed main(){
    	//freopen("t.in","r",stdin);
    	int len=0,eq=1;
    	while(true){
    		ch[++len]=getchar();
    		if(ch[len]=='#')break;
    	}
    	while(ch[eq]!='=')eq++;
    	//分别处理等号前后
    	//把右边的等价到左边
    	for(int i=len-1,j;i>eq;i=j-1){
    		j=i;
    		while(j-1>0&&isdigit(ch[j-1]))j--;
    		int type=-1;
    		if(ch[j-1]=='-')type=1;
    		for(int w=i;w>=j;w--)
    			a[++tot]=num(ch[w]-'0',i-w,type);
    		if(ch[j-1]=='+'||ch[j-1]=='-')j--;
    	} 
    	for(int i=eq-1,j;i>=1;i=j-1){
    		j=i;
    		while(j-1>0&&isdigit(ch[j-1]))j--;
    		int type=1;
    		if(ch[j-1]=='-')type=-1;
    		for(int w=i;w>=j;w--)
    			a[++tot]=num(ch[w]-'0',i-w,type);
    		if(ch[j-1]=='+'||ch[j-1]=='-')j--;
    	} 
    	//for(int i=1;i<=tot;i++)
    	//	printf("%d*%d ",a[i].get(),a[i].des);
    	check(a,tot);
    	for(int i=1;i<=tot;i++)
    		for(int j=0;j<8;j++)//枚举拿走的火柴
    			if(a[i].check(j))
    				for(int w=1;w<=tot;w++)
    					for(int k=0;k<8;k++)
    						if(!a[w].check(k)){
    							//将i的j放到w的k上
    							a[i].change(j);
    							a[w].change(k);
    							if(check(a,tot)){
    								int p=tot;
    								for(int i=1;i<=len;i++)
    									if(isdigit(ch[i]))putchar(a[p--].get()+'0');
    									else putchar(ch[i]);
    								return 0;
    							} 
    							a[i].change(j);
    							a[w].change(k);
    						}
    	printf("No"); 
    	return 0;
    }
    

    跑得慢了点但能过就对了

    • 1

    信息

    ID
    1443
    时间
    1000ms
    内存
    125MiB
    难度
    5
    标签
    递交数
    0
    已通过
    0
    上传者