2023年第八场蓝桥杯小白赛 4.求解线性方程组 递推+分类讨论

118 阅读2分钟

4.求解线性方程组【算法赛】 - 蓝桥云课 (lanqiao.cn)

题目说了xi只有0,1两种选择,那么ai只可能有0,1,2三种状态,我们对这三种状态分类讨论即可。

这道题是个递推题,观察题目我们发现一个规律:从a[2]开始,后面都是 x[i1]+x[i]+x[i+1]=a[i]x[i-1]+x[i]+x[i+1]=a[i]的形式(除了a[n]),因此我们只需要通过x1+x2=a[1]x1+x2=a[1]推出来x[1],x[2]的值,知道了x[1],x[2]的值我们就可以通过x1+x2+x3=a2x1+x2+x3=a2推出x3的值,剩下的x[i]可以用推x[3]的方式递归,循环推出。

image.png

接下来我们就考虑怎么推出来x[1],x[2]。

因为题目说了x[]数组只能由0,1两种数组成,而题目又告诉了我们a[i]的值,因此x1,x2有下面几种可能:


当a[1]=2时
当x1,x2=0的情况
当x1,x2=1的情况

当a1=1时
当x1=0,x2=1的情况
当x1=1,x2=0的情况

针对每一种情况我们都可以往后推出一种解。现在我们需要对每一组解都推出x3,然后推x[i]。

x[3]: image.png

x[i]:

x[i+1]=a[i]x[i1]x[i2]x[i+1]=a[i]-x[i-1]-x[i-2]

code

#include<iostream>
using namespace std;
const int N = 2e5+10;
int n;
int a[N],x[N],b[N];

void op()
{
	for (int i = 3; i < n; i++)
	{   
		x[i + 1] = a[i] - x[i] - x[i - 1];
	}
}
void sovel()
{
	cin >> n;
	for (int i = 1; i <= n; i++)cin >>a[i];
	if (a[1] == 2)x[1] = x[2] = 1; //因为x[i]只有1,0,两种可能,所以a[i]最大只能为2
	if (a[1] == 0)x[1] = x[2] = 0;
	x[3] = a[2] - a[1];  

	//从这以后就可以循环递推了
	if (a[1] == 1)  //a[1]=1的话有两种可能
	{
		//第一种可能
		x[1] = 0;
		x[2] = 1;

		op();   //由 0 1开头产生的递推
	    
		for (int i = 1; i <= n; i++)
		{
			b[i] = x[i - 1] + x[i] + x[i + 1];  //存储一下我们递推的结果
		    
			//如果说我们递推出来的b数组和a数组不一样,或者递推出来x[i]是负数(负数不可能和另一个数相加为1),那么说明不是0 1开头的这组解
			if (b[i] != a[i] || x[i] < 0)
			{
				//那么我们就要递推另一种解
				x[1] = 1;
				x[2] = 0;
				op();  //由 1,0开头产生的递推
				break;
			}

		}
	}


	for (int i = 1; i <= n; i++)cout << x[i] << " ";
}
int main()
{
	cin.tie(nullptr)->sync_with_stdio(false);
	int t=1;
  while(t--)
  sovel();
	return 0;
}