模线性方程组

Widget Factory

题目大意:
零件工厂生产若干种零件,生产每种零件都需要花费3~9天的时间。
由于工厂被收购,老员工被开除,新来的员工并不知道生产某种零件需要多长时间。只能依靠之前员工生产零件的记录,来计算零件所需生产时间。
每条记录包含以下信息:
该员工生产的零件总数k、该员工开始在工厂工作的时间、该员工被开除的时间(但是时间仅仅只是记录当天是星期几,无从知晓具体日期)
k个零件的编号也会记录在案
根据所给记录,计算生产各零件所需时间。

思路:
第一想法,设立未知数,求解方程。
对于编号为1~n的零件,设分别需要花费x1,x2,...,x3x_1,x_2,...,x_3x1​,x2​,...,x3​天。
一共给出m条记录,则可以列出m个方程。
关键是对于时间的处理,由于只给出起始时间是星期几,我们并无法算出精确的时间间隔是多少天,但由于生产一个零件最少需3天,最多也只要9天,我们将起始时间看成是同一个星期内的(相当于对7取余),如果算出生产某零件的天数比3天还少,那么直接加7。

其中,aija_{ij}aij​表示第i条记录中,第j个零件出现的次数,bib_ibi​表示第i条记录的时间间隔对7取余之后的结果。

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
#define pb push_back
#define mpi make_pair
#define fi first
#define se second
#define IOS ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
#define pi acos(-1)
using namespace std;
typedef long long ll;
const int maxn=1e3+10;
const ll mod=7;
const int INF=0x3f3f3f3f;
typedef pair<int,int> P;
typedef unsigned long long ull;
inline ll lowbit(ll x){return x&(-x);}
int a[maxn][maxn];
int x[maxn];
bool freeX[maxn];
int GCD(int a,int b){return b==0?a:GCD(b,a%b);
}
int LCM(int a,int b){return a/GCD(a,b)*b;
}
int get(char s[]){//将星期字符转为具体天if(s[0]=='M'&&s[1]=='O'&&s[2]=='N')return 1;else if(s[0]=='T'&&s[1]=='U'&&s[2]=='E')return 2;else if(s[0]=='W'&&s[1]=='E'&&s[2]=='D')return 3;else if(s[0]=='T'&&s[1]=='H'&&s[2]=='U')return 4;else if(s[0]=='F'&&s[1]=='R'&&s[2]=='I')return 5;else if(s[0]=='S'&&s[1]=='A'&&s[2]=='T')return 6;else if(s[0]=='S'&&s[1]=='U'&&s[2]=='N')return 7;
}
int Gauss(int equ,int var){for(int i=0;i<=var;i++){//初始化 x[i]=0;freeX[i]=true;}int col=0;int row;for(row=0;row<equ&&col<var;row++,col++){int maxRow=row;for(int i=row+1;i<equ;i++){//寻找当前列的最大值 if(abs(a[i][col])>abs(a[maxRow][col])){maxRow=i;}}if(maxRow!=row){//交换 for(int j=row;j<var+1;j++){swap(a[row][j],a[maxRow][j]);}}if(a[row][col]==0){//若寻找当前列最大值,交换之后,当前行当前列仍为0,则说明col列第row行以下全是0,接下来处理当前行的下一列(row不变,col+1) row--;continue;}for(int i=row+1;i<equ;i++){//上三角化 if(a[i][col]!=0){int lcm=LCM(abs(a[row][col]),abs(a[i][col]));int ta=lcm/abs(a[i][col]);int tb=lcm/abs(a[row][col]);if(a[i][col]*a[row][col]<0) tb*=-1;for(int j=col;j<var+1;j++){a[i][j]=((a[i][j]*ta-a[row][j]*tb)%mod+mod)%mod;}}}} /*求解*///无解:化简的增广阵中存在(0,0,...,a)这样的行,且a!=0for(int i=row;i<equ;i++){if(a[i][col]!=0){return -1;}}//无穷解: 在var*(var+1)的增广阵中出现(0,0,...,0)这样的行int temp=var-row;//自由变元有var-row个if(row<var){//返回自由变元数return temp;}//唯一解: 在var*(var+1)的增广阵中形成严格的上三角阵for(int i=var-1;i>=0;i--){int temp=a[i][var];for(int j=i+1;j<var;j++){if(a[i][j]!=0) temp-=a[i][j]*x[j];temp=((temp%mod)+mod)%mod;}//不断的循环取模判断,直到找出能整除的为止while(temp%a[i][i]!=0) temp+=mod;x[i]=(temp/a[i][i])%mod;}return 0;
}
int main(){int n,m;while(~scanf("%d%d",&n,&m)){if(n==0&&m==0) break;memset(a,0,sizeof(a));for(int i=0;i<m;i++){int k;char sta[5],end[5];scanf("%d %s %s",&k,sta,end);a[i][n]=((get(end)-get(sta)+1)%mod+mod)%mod;//计算时间间隔 for(int j=0;j<k;j++){int type;scanf("%d",&type);type--;//零件编号改为从0开始a[i][type]++;a[i][type]%=mod;              }}int free=Gauss(m,n);if(free==-1) printf("Inconsistent data.\n");else if(free==0){for(int i=0;i<n;i++){if(x[i]<3) x[i]+=mod;printf("%d ",x[i]);}    printf("\n");}else printf("Multiple solutions.\n");}return 0;
}

SETI

主要就是要读懂题目,列出方程组

每条消息可以被转译成一个整数序列a0,a1,...,an−1a_0,a_1,...,a_{n-1}a0​,a1​,...,an−1​,同时定义函数f(k)=∑i=0n−1aiki(mod)pf(k)=\sum_{i=0}^{n-1}a_ik^i(mod)pf(k)=∑i=0n−1​ai​ki(mod)p,且该函数的值始终(1≤k≤n1\leq k\leq n1≤k≤n)大于等于0,小于等于26。
现在对该函数再次“加密”,用小写字母来表示函数值,a代表1,不代表2,以此类推。用字符’*'来表示0。
对于样例1
31 aaa
表示p=31
f(1)=a0⋅10+a1⋅11+a2⋅12=1f(1)=a_0\cdot1^0+a_1\cdot1^1+a_2\cdot1^2=1f(1)=a0​⋅10+a1​⋅11+a2​⋅12=1
f(2)=a0⋅20+a1⋅21+a2⋅22=1f(2)=a_0\cdot2^0+a_1\cdot2^1+a_2\cdot2^2=1f(2)=a0​⋅20+a1​⋅21+a2​⋅22=1
f(3)=a0⋅30+a1⋅31+a2⋅32=1f(3)=a_0\cdot3^0+a_1\cdot3^1+a_2\cdot3^2=1f(3)=a0​⋅30+a1​⋅31+a2​⋅32=1
很显然,高斯消元求解三元一次方程组,即可。

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
#define pb push_back
#define mpi make_pair
#define fi first
#define se second
#define IOS ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
#define pi acos(-1)
using namespace std;
typedef long long ll;
const int maxn=1e3+10;
int mod;
const int INF=0x3f3f3f3f;
typedef pair<int,int> P;
typedef unsigned long long ull;
inline ll lowbit(ll x){return x&(-x);}
int a[maxn][maxn];
int x[maxn];
bool freeX[maxn];
int GCD(int a,int b){return b==0?a:GCD(b,a%b);
}
int LCM(int a,int b){return a/GCD(a,b)*b;
}
int ksm(int a,int b){int ans=1;while(b){if(b&1) ans=(ans*a)%mod;a=(a*a)%mod;b>>=1;}return ans;
}
int Gauss(int equ,int var){for(int i=0;i<=var;i++){//初始化 x[i]=0;freeX[i]=true;}int col=0;int row;for(row=0;row<equ&&col<var;row++,col++){int maxRow=row;for(int i=row+1;i<equ;i++){//寻找当前列的最大值 if(abs(a[i][col])>abs(a[maxRow][col])){maxRow=i;}}if(maxRow!=row){//交换 for(int j=row;j<var+1;j++){swap(a[row][j],a[maxRow][j]);}}if(a[row][col]==0){//若寻找当前列最大值,交换之后,当前行当前列仍为0,则说明col列第row行以下全是0,接下来处理当前行的下一列(row不变,col+1) row--;continue;}for(int i=row+1;i<equ;i++){//上三角化 if(a[i][col]!=0){int lcm=LCM(abs(a[row][col]),abs(a[i][col]));int ta=lcm/abs(a[i][col]);int tb=lcm/abs(a[row][col]);if(a[i][col]*a[row][col]<0) tb*=-1;for(int j=col;j<var+1;j++){a[i][j]=((a[i][j]*ta-a[row][j]*tb)%mod+mod)%mod;}}}} /*求解*///无解:化简的增广阵中存在(0,0,...,a)这样的行,且a!=0for(int i=row;i<equ;i++){if(a[i][col]!=0){return -1;}}//无穷解: 在var*(var+1)的增广阵中出现(0,0,...,0)这样的行int temp=var-row;//自由变元有var-row个if(row<var){//返回自由变元数return temp;}//唯一解: 在var*(var+1)的增广阵中形成严格的上三角阵for(int i=var-1;i>=0;i--){int temp=a[i][var];for(int j=i+1;j<var;j++){if(a[i][j]!=0) temp-=a[i][j]*x[j];temp=((temp%mod)+mod)%mod;}//不断的循环取模判断,直到找出能整除的为止while(temp%a[i][i]!=0) temp+=mod;x[i]=(temp/a[i][i])%mod;}return 0;
}
int main(){int t;scanf("%d",&t);while(t--){char st[100];scanf("%d %s",&mod,st);int m=strlen(st);int n=m;for(int i=0;i<m;i++){//构造方程组if(st[i]=='*') a[i][n]=0;else a[i][n]=st[i]-'a'+1;for(int j=0;j<n;j++){a[i][j]=ksm(i+1,j)%mod;}}int free=Gauss(m,n);//解方程组for(int i=0;i<n;i++){printf("%d ",x[i]);}printf("\n");}return 0;
}

异或方程组

EXTENDED LIGHTS OUT

有一个5×65\times 65×6 的矩形,每个单元格都有两种状态 1、0,改变一个单元格的状态会使得其周围 4 个单元格状态也改变,现在给出每个单元格的状态,要求输出一种能将所有单元格全变为 0 的方案

思路:
将当前状态转变成全0的状态的方案,与将全0状态转换成当前状态的方案相同。
每个单元格仅有0和1两种状态,而且单元格状态的改变和异或运算相同(0^ 1 ^ 1=0),故使用异或运算。
每改变一个单元格的状态,都会导致整个矩阵状态的改变,因此对于每一个单元格都需要列一个等式,将其状态表示出来。


其中,ai,ja_{i,j}ai,j​表示第i个单元格是否受第j个灯的影响,若有影响则赋值为1,否则赋值为0。bib_ibi​表示第i个单元格的初始状态(输入矩阵)。
解上述异或方程组,解集{x0,x1,x2,...,x29}\{x_0,x_1,x_2,...,x_{29}\}{x0​,x1​,x2​,...,x29​},即为一种操作方案,它能将当前状态,变为单元格全为0的状态。

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
using namespace std;
const int maxn=1e3+10;
const int INF=0x3f3f3f3f;
int a[maxn][maxn];
int x[maxn];
bool freeX[maxn];
int Gauss(int equ,int var){for(int i=0;i<=var;i++){//初始化 x[i]=0;freeX[i]=true;}int col=0;int row;for(row=0;row<equ&&col<var;row++,col++){int maxRow=row;for(int i=row+1;i<equ;i++){//寻找当前列的最大值 if(abs(a[i][col])>abs(a[maxRow][col])){maxRow=i;}}if(maxRow!=row){//交换 for(int j=row;j<var+1;j++){swap(a[row][j],a[maxRow][j]);}}if(a[row][col]==0){//若寻找当前列最大值,交换之后,当前行当前列仍为0,则说明col列第row行以下全是0,接下来处理当前行的下一列(row不变,col+1) row--;continue;}for(int i=row+1;i<equ;i++){//上三角化 if(a[i][col]!=0){for(int j=col;j<var+1;j++){a[i][j]^=a[row][j];}}}} /*求解*///唯一解: 在var*(var+1)的增广阵中形成严格的上三角阵for(int i=var-1;i>=0;i--){x[i]=a[i][var];for(int j=i+1;j<var;j++){x[i]^=(a[i][j]&&x[j]);}}return 0;
}
int dir[][2]={{-1,0},{1,0},{0,-1},{0,1}};
int main(){int t;scanf("%d",&t);for(int tt=1;tt<=t;tt++){memset(a,0,sizeof(a));for(int i=0;i<5;i++){for(int j=0;j<6;j++){//初始化状态矩阵int p=i*6+j;a[p][p]=1; for(int k=0;k<4;k++){int x=i+dir[k][0];int y=j+dir[k][1];if(x>=0&&x<5&&y>=0&&y<6){a[x*6+y][p]=1;}}}}for(int i=0;i<30;i++){scanf("%d",&a[i][30]);} Gauss(30,30);printf("PUZZLE #%d\n",tt);for(int i=0;i<5;i++){for(int j=0;j<6;j++){printf("%d",x[i*6+j]);if(j==5) printf("\n");else printf(" ");}}}return 0;
}

开关问题

有N个相同的开关,每个开关都与某些开关有着联系,每当你打开或者关闭某个开关的时候,其他的与此开关相关联的开关也会相应地发生变化,即这些相联系的开关的状态如果原来为开就变为关,如果为关就变为开。你的目标是经过若干次开关操作后使得最后N个开关达到一个特定的状态。对于任意一个开关,最多只能进行一次开关操作。你的任务是,计算有多少种可以达到指定状态的方法。(不计开关操作的顺序)
Input
输入第一行有一个数K,表示以下有K组测试数据。
每组测试数据的格式如下:
第一行 一个数N(0 < N < 29)
第二行 N个0或者1的数,表示开始时N个开关状态。
第三行 N个0或者1的数,表示操作结束后N个开关的状态。
接下来 每行两个数I J,表示如果操作第 I 个开关,第J个开关的状态也会变化。每组数据以 0 0 结束。
Output
如果有可行方法,输出总数,否则输出“Oh,it’s impossible~!!” 不包括引号
Sample Input
2
3
0 0 0
1 1 1
1 2
1 3
2 1
2 3
3 1
3 2
0 0
3
0 0 0
1 0 1
1 2
2 1
0 0
Sample Output
4
Oh,it’s impossible~!!

思路:
与上一题“EXTENDED LIGHTS OUT”的区别在于,从当前状态变为给定状态,而不再是单元格全为0的状态。
但其实是一样的做法,上题中方程组等号右边bib_ibi​为每个单元格的最终状态,其实是每个单元格当前状态和最终状态的异或值。(任何数和0异或,值不变)
同样的思路,列出方程组,但由于此题并未保证一定有解,因此有三种情况。
1、无解:直接按题目要求输出
2、有解(无穷解/唯一解):
求出自由元的个数,由于每个自由元都可以取两个状态(0或1),所以方案总数即为2自由元个数2^{自由元个数}2自由元个数
注意:
题目所给“每行两个数I J,表示如果操作第 I 个开关,第J个开关的状态也会变化”,说明第i个开关会影响第j个开关,也就是说第j个开关会受第i个开关的影响,因此赋值时应为:a[j][i]=1a[j][i]=1a[j][i]=1

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
using namespace std;
const int maxn=1e3+10;
int a[maxn][maxn];
int x[maxn];
bool freeX[maxn];
int Gauss(int equ,int var){for(int i=0;i<=var;i++){//初始化 x[i]=0;freeX[i]=true;}int col=0;//当前处理的列 int num=0;//自由元序号 int row;for(row=0;row<equ&&col<var;row++,col++){int maxRow=row;for(int i=row+1;i<equ;i++){//寻找当前列的最大值 if(abs(a[i][col])>abs(a[maxRow][col])){maxRow=i;}}if(maxRow!=row){//交换 for(int j=row;j<var+1;j++){swap(a[row][j],a[maxRow][j]);}}if(a[row][col]==0){//若寻找当前列最大值,交换之后,当前行当前列仍为0,则说明col列第row行以下全是0,接下来处理当前行的下一列(row不变,col+1) freeX[num++]=col;//记录自由元 row--;continue;}for(int i=row+1;i<equ;i++){//上三角化 if(a[i][col]!=0){for(int j=col;j<var+1;j++){a[i][j]^=a[row][j];}}}} /*求解*///无解:化简的增广阵中存在(0,0,...,a)这样的行,且a!=0for(int i=row;i<equ;i++)if(a[i][col]!=0) return -1;//无穷解 if(var>row) return var-row;//唯一解: 在var*(var+1)的增广阵中形成严格的上三角阵
//  for(int i=var-1;i>=0;i--){//      x[i]=a[i][var];
//      for(int j=i+1;j<var;j++){//          x[i]^=(a[i][j]&&x[j]);
//      }
//  }return 0;
}
int s[maxn],e[maxn];
int main(){int t;scanf("%d",&t);while(t--){int n;scanf("%d",&n);for(int i=0;i<n;i++){scanf("%d",&s[i]);}for(int i=0;i<n;i++){scanf("%d",&e[i]);}memset(a,0,sizeof(a));for(int i=0;i<n;i++){a[i][n]=s[i]^e[i];a[i][i]=1;}int x,y;while(~scanf("%d%d",&x,&y)&&(x+y)){ a[y-1][x-1]=1;} int free=Gauss(n,n);if(free==-1) puts("Oh,it's impossible~!!");else printf("%d\n",1<<free);}return 0;
}

线性代数--高斯消元法相关推荐

  1. 线性代数 --- 高斯消元法的几何解释

    用几何图形来更加形象的展示高斯消元法的过程 高斯消元法不改变方程组的解: 现有如下2x2方程组: Tips: 下面用矩阵的行视图来展示方程组消元前后的差异. 首先,可以看到,不论是消元前还是消元后,两 ...

  2. 【学习笔记】线性代数全家桶(在编程竞赛中的应用)

    整理的算法模板合集: ACM模板 点我看算法全家桶系列!!! 实际上是一个全新的精炼模板整合计划 目录 0x00. 矩阵 0x01. 矩阵 0x02. 矩阵的加法与数量乘法 0x03. 矩阵乘法 0x ...

  3. 2020 ICPC 济南 A Matrix Equation (高斯消元)

    题目链接A-Matrix Equation 第 45 届国际大学生程序设计竞赛(ICPC)亚洲区域赛(济南) 题目描述 We call a matrix "01 Square" i ...

  4. MATLAB数值分析学习笔记:线性代数方程组的求解和高斯消元法

    工程和科学计算的许多基本方程都是建立在守恒定律的基础之上的,比如质量守恒等,在数学上,可以建立起形如 [A]{x}={b} 的平衡方程.其中{x}表示各个分量在平衡时的取值,它们表示系统的状态或响应: ...

  5. 【线性代数】高斯消元法与矩阵的初等变换

    上一篇:矩阵及其运算[写在前面的话]众所周知,线性代数在计算机应用方面也是比较广的(比如人工智能等前沿科技领域).所以...在CSDN记录线性代数的知识不为过吧,哈哈(//狗头保命).想要学线性代数的 ...

  6. 漫步线性代数三——高斯消元法

    高斯消元法实例 了解消元法最好的方式是看例子.我们以三维开始: Original system 2u4u−2u+−+v6v7v++w2w===5−29(1) \begin{equation} {\rm ...

  7. 线性代数 --- 什么是高斯消元法,什么又是高斯-若尔当消元法?

    写在最前面: 我这个人比较喜欢炫耀,尤其发现别人在我面前炫耀的时候,我就会试图用我所学的知识盖过他的锋芒.所以呢,当初在Gilbert string老爷爷的课程里面第一次听到高斯若尔当这个词汇的时候, ...

  8. 线性代数:第一章 线性方程组

    本讲义是自己上课所用幻灯片,里面没有详细的推导过程(笔者板书推导)只以大纲的方式来展示课上的内容,以方便大家下来复习. 从本章开始,我们一起来学习线性代数的有关知识,线性代数的应用之一就是求解复杂方程 ...

  9. 免费在线阅读:用于计算机视觉、机器学习、机器人的线性代数丨资源

    郭一璞 发自 凹非寺  量子位 报道 | 公众号 QbitAI 研究机器学习.计算机视觉,总离不开数学,尤其是--线性代数. 要是没有一定数学基础的话,当你看到SVM.拉格朗日乘数等各种复杂术语的时候 ...

最新文章

  1. 实现Java中的ArrayList
  2. 【HAOI2015】树上染色
  3. cnpm 安装文件找不到_大师操作win7系统电脑软件中找不到已经安装字体的恢复步骤...
  4. 2016OSC源创会年终盛典-综合技术专场-张小刚
  5. Docker-Compose快速搭建Oracle-12C系统
  6. ncurses初始化函数:raw(),cbreak(),echo(),noecho(),keypad(),halfdelay()
  7. k8s高可用集群_搭建高可用集群(部署master1节点初始化)---K8S_Google工作笔记0057
  8. EnterCriticalSection 多线程操作相同数据遇到的问题(线程锁)
  9. java+opencv+intellij idea实现人脸识别
  10. 1设计一身高体重测量仪c语言,身高体重测量仪使用经验
  11. CSDN使用MD编辑器写博客如何让图片居中(调整图片位置大小)MD编辑器学习笔记
  12. 一次悲惨的被挖矿经历
  13. 【解决】Keil中创建工程时出现-arm_math.h(xxx): warning: #xxxx-D: unrecognized GCC pragma错误
  14. 软件项目管理——人力资源管理
  15. 利用RunLoop空闲时间执行预缓存任务
  16. 3种侧链压缩方法让音乐鼓点更有力—FL Studio教程
  17. 微信的QQ邮箱助手不提醒,怎么解决?
  18. 2022年下半年网络工程师上午综合知识真题答案解析
  19. 【MySQL基础】什么是MySQL约束?什么是主键约束?
  20. 为什么Markdown+R有较大概率成为科技写作主流? ← 阳志平的个人网站::技术

热门文章

  1. 华秋电子亮相2022深圳集成电路峰会
  2. Android Socket 连接设备接收H264裸流数据并解码播放 Demo
  3. 中国289个地级市商业信用环境指数数据(2010-2021)
  4. c语言定义y1代表英里数,河南理工大学C语言第二章课后习题答案.ppt
  5. Python学习笔记(十九)面向对象 - 继承
  6. AI 浪淘沙 (week125-129)
  7. 《MATLAB SYNTAX》第5章 数值计算
  8. 北方经贸杂志北方经贸杂志社北方经贸编辑部2023年第1期目录
  9. Class not found :“ test” 的解决方法
  10. Vue前端时间戳格式化