2021图森未来杯 A.【Abstract Algebra】
(为防止误解题意,接下来我说的1,2,3,4号位分别代表矩阵的第一排第一列,第一排第二列,第二排第一列,第二排第二列的数字)
题目大意:现在我们有俩个初始矩阵分别为
现在给出一个矩阵
现在已知
我们要通过对A矩阵和B矩阵如何处理才能转化成X?(操作次数需要小于等于4,且操作只能是使用矩阵乘法)
输出第一行先输出操作次数m,接下来m行
输出每一步的操作过程,即对A怎么操作或者对B怎么操作,题目有多解,输出任意一种即可
由于操作步数的限制,我们要合理的规划每一步的操作,要对任意一个x矩阵都成立,那我们可以先试一下A矩阵和B矩阵对任意的一个X矩阵会产生什么样的影响
通过图片我们可以很清楚的发现一个很重要的信息点, 的变化只是在二号位这个位置加1,即可以得知
这只是我们通过观察得到的一个信息点,其他的信息还没有利用上。
我们现在还知道一个很重要的信息就是
那么这告诉我们abcd中至少有一个位置是0,我们假设现在这个为0的位置是c,即
若c=0,我们可以推断出来,ad=1,那么分俩种情况,a=d=1或者a=d=-1
对应的俩个矩阵就分别是
这时候可以很明显想到我们前面发现的信息,说明
那么X2呢?看上图我们可以发现 可以起到取负的作用,我们,因此我们可以得到
截至目前,我们已经走出了很大一步,就是将c等于0的情况全部转换为了AB矩阵的变化,且只需要操作1次或者2次(第二种情况属于操作俩次,这是题意说明的)
回到问题本身,假如我们每一次都要通过这样子思考来判断四个位置等于0的情况会不会太麻烦了,(内心OS:我tm线代学的不好看不出规律啊!!!),那我们换个角度思考一下,c=0的情况这么简单易懂,那我们能不能通过简单的变换(操作次数越少越简单越好,因为要让自己看懂嘛QAQ)让我其他位置等于0的情况也转换成c=0这种easy模式呢?答案是必然的
我们来举个可爱的栗子
现在我的a=0,即
我们的目标有俩个
1.把0位变到3号位
2.在满足0位是三号位的情况下,一号位和四号位相乘要等于1(这样子就是c=0的情况了)
回到最开始的那幅图,防止你们懒得翻和方便阅读,我再贴一次
我们可以发现当我们用B矩阵左乘X矩阵时,可以将上下俩排互换位置
神奇地将0位从一号位转到了三号位,那我们现在要得到X,那不是很简单嘛,我们只需要将目标矩阵左乘一个B的逆矩阵不就得到X了吗?
即
只用了简简单单一步操作就变成了我们最开始的c=0的情况,一切问题都轻松解决,这时候就只用考虑c=1&&b=-1或者c=-1&&b==1的这俩种对应c=0的俩种情况了
通过这个简单的例子,我们悟到了一个道理,噢,逆矩阵真是个神奇的东西。
那我们就继续来简单快速讨论一下b=0和d=0的情况吧
先来讨论d=0的情况,因为这个和a=0一样简单
我们通过图片观察就能发现只要用B矩阵右乘X矩阵,就能使第一列和第二列互换位置,之后的讨论和a=0的情况相同
即
接下来考虑b=0的情况,我们通过上述得知左乘B矩阵可以使上下互换,右乘B矩阵可以使得左右互换,那tmd低能儿都知道了,我们只要先左乘一个B,再右乘一个B,那不是就可以将0位转到三号位了吗???
反过来即
至此,我们已经将四个位置等于0的情况全部转换为了0位等于三号位这个最简单的情况,且所有操作次数都控制在了三以内,这已经是最优解了,我们只需要简单模拟一下上述过程然后输出即可
代码如下:
#include<bits/stdc++.h> #define ll long long using namespace std; const int maxn=1e7+5; inline ll read(){ ll f = 1; ll x = 0;char ch = getchar();while(ch>'9'||ch<'0') {if(ch=='-') f=-1; ch = getchar();}while(ch>='0'&&ch<='9') x = (x<<3) + (x<<1) + ch - '0', ch = getchar();return x*f; } int main() { int _;_=read();while(_--) { int a=read(),b=read(),c=read(),d=read(); if(a==0) { puts("2"); if(c==1&&b==-1) { puts("B -1"); printf("A %d\n",d); } else if(c==-1&&b==1) { puts("B 1"); printf("A %d\n",-d); } } else if(b==0) { puts("3"); if(a==1&&d==1) { puts("B 1"); printf("A %d\n",-c); puts("B -1"); } else if(a==-1&&d==-1) { puts("B -1"); printf("A %d\n",c); puts("B -1"); } } else if(c==0) { if(a==1&&d==1) { puts("1"); printf("A %d\n",b); } else if(a==-1&&d==-1) { puts("2"); puts("B 2"); printf("A %d\n",-b); } } else if(d==0) { if(b==1&&c==-1) { puts("3"); puts("B 2"); printf("A %d\n",-a); puts("B -1"); } else if(b==-1&&c==1) { puts("2"); printf("A %d\n",a); puts("B -1"); } } } }