林大陈宇老师的原创高斯

基于MATLAB的电池等效电路模型(ECM)仿真,用于分析电气行为和动态响应.zip 1.版本:matlab2014a/2019b/2024b 2.附赠案例数据可直接运行。 3.代码特点:参数化编程、参数可方便更改、代码编程思路清晰、注释明细。 4.适用对象:计算机,电子信息工程、数学等专业的大学生课程设计、期末大作业和毕业设计。 立即下载

最后1 行,有x4=b4;
第3 行: x4+x3=b3,已经求出x4=b4 了,带入第3 行,可求出x3;同理,把x4 x3 带入
第2 行,还可求出x2;把x4 x3 x2 带入到第1 行,可求出x1;
这就是回带。
回带总结:从最后1 行,逐一往回带,从最后1 行代回到第1 行。
最关键的时候到了:当无穷多解时,最后几行都是0;没法回带;而某些题目在无穷多
解时还要你求最小或最优解,没办法,就得枚举最后行为0 的那几个解;
如:
1 2 4 3 3
0 1 3 2 3
0 0 1 0 2
0 0 0 0 0
可见最后的x4 没法解,如果题中给定x4 的范围,那就枚举x4,然后回带;枚举1 次x4
就回带1 次得到一组(x1 x2 x3 x4 );然后根据题意找最优的,具体题目具体分析。
说得够详细的了,下面拿出有效的高消模板:
-----------------------------------再次复习过程--------------------------------------------------------------
确定系数矩阵和增广矩阵
消元
If 如果有系数矩阵=0,增广矩阵不为0,则无解;
{
例: 0 0 0 0 2
有这样的行就没解,0*x1+0*x2+0*x3+0*x4=2;没这样的x
}
If (var-k>0) //有多个解//var 变量数,k 是主对角线上连续1 的个数
{
枚举最后几行(全为0) 的那几个解;枚举或dfs 都行
回带可以求出很多组解;
}
If (var-k==0) //唯一解
{
直接回带
}
-----------------------------复习完成----------------------------------------------------------------------

int a[maxn][maxn+1],x[maxn];//a 是系数矩阵和增广矩阵,x 是最后存放的解
// a[][maxn]中存放的是方程右面的值(bi)
int equ,var;//equ 是系数阵的行数,var 是系数矩阵的列数(变量的个数)
int free_num,ans=100000000;
int abs1(int num) //取绝对值
{
if (num>=0) return num;
else
return -1*num;
}
void Debug(void) //调试输出,看消元后的矩阵值,提交时,就不用了
{
int i, j;
for (i = 0; i < equ; i++)
{
for (j = 0; j < var + 1; j++)
{
cout << a[i][j] << " ";
}
cout << endl;
}
cout << endl;
}
inline int gcd(int a, int b) //最大公约数
{
int t;
while (b != 0)
{
t = b;
b = a % b;
a = t;
}
return a;
}

inline int lcm(int a, int b) //最小公倍数
{
return a * b / gcd(a, b);
}
void swap(int &a,int &b){int temp=a;a=b;b=temp;} //交换2 个数
int Gauss()
{
int k,col = 0; //当前处理的列
for(k = 0;k < equ && col < var;++k,++col)
{
int max_r = k;
for(int i = k+1;i < equ; ++i)
if(a[i][col] > a[max_r][col])
max_r = i;
if(max_r != k)
{
for(int i = k;i < var + 1; ++i)
swap(a[k][i],a[max_r][i]);
}
if(a[k][col] == 0)
{
k--;
continue;
}
for(int i = k+1;i < equ; ++i)
{
if(a[i][col] != 0)
{
int LCM = lcm(a[i][col],a[k][col]);
int ta = LCM/a[i][col], tb = LCM/a[k][col];
if(a[i][col]*a[k][col] < 0)
tb = -tb;
for(int j = col;j < var + 1; ++j)
a[i][j] = ( (a[i][j]*ta)%2 - (a[k][j]*tb)%2 + 2 ) % 2; //a[i][j]只有
0 和1 两种状态
}
}
}

//上述代码是消元的过程,行消元完成
//解下来2 行,判断是否无解
//注意K 的值,k 代表系数矩阵值都为0 的那些行的第1 行
for(int i = k;i < equ; ++i)
if(a[i][col] != 0) return -1; // 无解返回 -1
//Debug();
//唯一解或者无穷解,k<=var
//var-k==0 唯一解;var-k>0 无穷多解,自由解的个数=var-k
//能执行到这,说明肯定有解了,无非是1 个和无穷解的问题。
//下面这几行很重要,保证秩内每行主元非0,且按对角线顺序排列,就是检查列
for(int i = 0; i <equ; ++i)//每一行主元素化为非零
if(!a[i][i])
{
int j;
for(j = i+1;j<var;++j)
if(a[i][j])
break;
if(j == var)
break;
for(int k = 0;k < equ; ++k)
swap(a[k][i],a[k][j]);
}
// ----处理保证对角线主元非0 且顺序,检查列完成
// free_num=k;
if (var-k>0) {
//无穷多解,先枚举解,然后用下面的回带代码进行回带;
//这里省略了下面的回带的代码;不管唯一解和无穷解都可以回带,只不过无穷解
//回带时,默认为最后几个自由变元=0 而已。
}
if (var-k==0)//唯一解时
{
//下面是回带求解代码,当无穷多解时,最后几行为0 的解默认为0;
for(int i = k-1;i >= 0; --i) //从消完元矩阵的主对角线非0 的最后1 行,开始往
//回带
{
int tmp = a[i][var] % 2;

for(int j = i+1;j < var; ++j) //x[i]取决于x[i+1]--x[var]啊,所以后面的解对前面的解
有影响。
if(a[i][j] != 0)
tmp = ( tmp - (a[i][j]*x[j])%2 + 2 ) % 2;
//if (a[i][i]==0) x[i]=tmp; //最后的空行时,即无穷解得
//else
x[i] = (tmp/a[i][i]) % 2; //上面的正常解
}
//回带结束了
}
}
--------------------------对上面模板的说明---------------------------------------------------------------
因为我们要解决的问题,基本上都是解都是出于0-1 这2 个数,所以要对2 取余;
如果想对普通的正数解方程,那自己把对2 取余删掉就行了;
下面这几道题要各个搞定才行:
POJ 1222 EXTENDED LIGHTS OUT
http://acm.pku.edu.cn/JudgeOnline/problem?id=1222
POJ 1681 Painter's Problem
http://acm.pku.edu.cn/JudgeOnline/problem?id=1681
POJ 1753 Flip Game
http://acm.pku.edu.cn/JudgeOnline/problem?id=1753
POJ 1830 开关问题
http://acm.pku.edu.cn/JudgeOnline/problem?id=1830
POJ 3185 The Water Bowls
http://acm.pku.edu.cn/JudgeOnline/problem?id=3185
开关窗户,开关灯问题,很典型的求解线性方程组的问题。方程数和变量数均为
行数*列数,直接套模板求解即可。但是,当出现无穷解时,需要枚举解的情况,
因为无法判断哪种解是题目要求最优的。
POJ 2947 Widget Factory poj 2065
http://acm.pku.edu.cn/JudgeOnline/problem?id=2947
求解同余方程组问题。与一般求解线性方程组的问题类似,只要在求解过程中加
入取余即可。
注意:当方程组唯一解时,求解过程中要保证解在[3, 9]之间。
分下类: 1222 有唯一解 太简单

1753 3185 2965 高斯+枚举,我要详细讲(黑板上)
2947 2065 同余方程
先说1222 这题:
题目大意:给你一个5*6 的矩阵,矩阵里每一个单元都有一个灯和一个
开关,如果按下此开关,那么开关所在位置的那个灯和开关前后左右的
灯的状态都会改变(即由亮到不亮或由不亮到亮)。给你一个初始的灯的
状态,问怎样控制每一个开关使得所有的灯最后全部熄灭(此题保证有
唯一解)。
解题思路:高斯消元。很显然每个灯最多只需要按1 下(因为按两
下和没有按是一个效果)。我们可以定义30 和未知数x0、
x1.......x29 代表每一个位置的开关是否被按。那么对于每一个灯
的状态可以列一个方程,假设位置(i,j)处的开关为x(i*6+j),那么
我们就可以列出方程:
x(i*6+j)+x((i-1)*6+j)+x((i+1)*6+j)+x(i*6+j-1)+x(i*6+j+1) =
bo(mod 2)
(括号里的数字为x 的下标,这里假设这些下标都是符合要求的,即
都在矩形内,如果不在则可以去掉,当这个灯初始时是开着的,那
么bo 为1,否则为0)
这样可以列出30 个方程,然后用高斯消元解这个方程组即可。
我的补充:题目给定后,我立刻知道了该题,呵呵,有唯一解;
怎么判断出的呢? 5 行6 列,已经固定了;每个灯的方程也固定了(系数矩阵);只有
开始时灯的状态会变,开始时灯的状态只能决定增广矩阵的最后1 列;因为系数矩阵式固定
的,而系数矩阵能决定该方程是否有唯一解和多个解;编好代码后,自己 deBUG 一下,也
就是把a 这个矩阵输出一下,自己look 一下,发现没有都是0 的行,秩=5;
所以模板里只要算一下 (var-k==0)是,回带就行了;
#include <iostream>
#include <cstring>
#include <cmath>
#include <stdio.h>
using namespace std;

const int maxn = 30;
int equ, var; // 有equ 个方程,var 个变元。增广阵行数为equ, 分别为0 到equ - 1,列数为
var + 1,分别为0 到var.
int a[maxn][maxn+1];
int x[maxn]; // 解集.
bool free_x[maxn+1]; // 判断是否是不确定的变元.
int free_num;
int abs1(int num)
{
if (num>=0) return num;
else
return -1*num;
}
void Debug(void)
{
int i, j;
for (i = 0; i < equ; i++)
{
for (j = 0; j < var + 1; j++)
{
cout << a[i][j] << " ";
}
cout << endl;
}
cout << endl;
}
inline int gcd(int a, int b)
{
int t;
while (b != 0)
{
t = b;
b = a % b;

a = t;
}
return a;
}
inline int lcm(int a, int b)
{
return a * b / gcd(a, b);
}
void swap(int &a,int &b){int temp=a;a=b;b=temp;}
int Gauss_new()
{
int k,col = 0; //当前处理的列
for(k = 0;k < equ && col < var;++k,++col)
{
int max_r = k;
for(int i = k+1;i < equ; ++i)
if(a[i][col] > a[max_r][col])
max_r = i;
if(max_r != k)
{
for(int i = k;i < var + 1; ++i)
swap(a[k][i],a[max_r][i]);
}
if(a[k][col] == 0)
{
k--;
continue;
}
for(int i = k+1;i < equ; ++i)
{
if(a[i][col] != 0)
{
int LCM = lcm(a[i][col],a[k][col]);
int ta = LCM/a[i][col], tb = LCM/a[k][col];
if(a[i][col]*a[k][col] < 0)
tb = -tb;
for(int j = col;j < var + 1; ++j)

a[i][j] = ( (a[i][j]*ta)%2 - (a[k][j]*tb)%2 + 2 ) % 2; //a[i][j]只有0 和
1 两种状态
}
}
}
for(int i = k;i < equ; ++i)
if(a[i][col] != 0) return -1; // 无解返回 -1
//唯一解或者无穷解,k<=var,这里直接回带了,知道有唯一解啊
for(int i = k-1;i >= 0; --i)
{
int tmp = a[i][var] % 2;
for(int j = i+1;j < var; ++j)
if(a[i][j] != 0)
tmp = ( tmp - (a[i][j]*x[j])%2 + 2 ) % 2;
x[i] = (tmp/a[i][i]) % 2;
}
return 0;
}
int main(void)
{
// freopen("Input.txt", "r", stdin);
int i, j,t,t1;
cin>>t;
t1=t;
equ=30;
var=30;
while (t--)
{
memset(a, 0, sizeof(a));
memset(x, 0, sizeof(x));
//memset(free_x, 1, sizeof(free_x)); // 一开始全是不确定的变元.
//下面要根据位置计算a[i][j];

for (i = 0; i < 5; i++)
{
for (j = 0; j < 6; j++)
{
/* for(int k=0;k<4;k++)
{
int ni=i+di[k];
int nj=j+dj[k];
if(inlim(ni,nj))
{
a[i*6+j][ni*6+nj]=1;
}
}
*/
if (i-1>=0) a[i*6+j][(i-1)*6+j]=1; //计算上面的位置
if (i+1<=4) a[i*6+j][(i+1)*6+j]=1;//计算下面的位置
if (j-1>=0) a[i*6+j][i*6+j-1]=1;//计算左面的位置
if (j+1<=5) a[i*6+j][i*6+j+1]=1; //计算右面的位置
a[i*6+j][i*6+j]=1;//别忘了计算自己
cin>>a[i*6+j][30];
//scanf("%d", &a[i][j]);
}
}
// Debug
//free_num = Gauss();
free_num=Gauss_new();
if (free_num == -1) printf("无解!\n");
else if (free_num >= 0)
{
int na_num=0;
printf("PUZZLE #%d\n",t1-t);
for (i = 0; i < var; i++)
{
na_num++;
if (na_num%6==0) {printf("%d\n",x[i]);}
else

printf("%d ",x[i]);
}
}
// printf("\n");
}
return 0;
}
------------------------------------1222-----------over--------------------------------------------------------------------
重点说下1753 这题:本题用guass 还是比较牛的,速度很快啊
题意:
有4*4 的正方形,每个格子要么是黑色,要么是白色,当把一个格子的颜色改变
(黑->白或者白->黑)时,其周围上下左右(如果存在的话)的格子的颜色也被反转,
问至少反转几个格子可以使4*4 的正方形变为纯白或者纯黑?
本题求都变白或变黑的最小格子数。
分析:求都变白的最小格子数;再求变黑的最小格子数,输出2 者最小值即可;
这里说下本类问题的bi 的赋值,bi 就是曾广矩阵的最后1 列;
其实就是开始的矩阵(0-1),和最终矩阵的(0-1)做异或;相同的格子为0,不同的格子值
为1;这类问题都一样的;
本体4*4 的矩阵固定,方法固定,只是初始状态不固定,还是先把代码先敲进去,用样例输
入,用 debug()把消元后的a 的结果输出到屏幕上看看,看看有几个解是未知的,共16 个

方程:
1100100000000000
0111001000000000
0010110000000000
0001110100000000
0000110101000000
0000011110000000
0000001101010000
0000000111100000
0000000010111000
0000000001111010
0000000000110100
0000000000010011
0000000000000000
0000000000000000
0000000000000000
0000000000000000
最后4 行都是0,则最后4 个解变量是无穷解;
X15 x14 x13 x12 只能取0 或1,枚举 2^4 共16 中情况,枚举1 次,回带1 次,算出1
组解,记录解变量和最小的。
0 000 0001 0010 0011 ----------1111 共16 个,说得太详细了,枚举可以循环
For (i=1----16)
{
0 0 0 0 // 每次根据i 值,产生0 0 0 0 还是 00 10 ,就是x15 x14 x13 x12 的值
回带
得到解
和是否最小
}
这是16 种情况,要是更多,还是用dfs()吧,也简单的要命!
--------------------------------下位直接枚举的代码---超短--------------------------------
• for(i=0,min=17;i<16;++i){ //枚举有解的16 种情况
• for(j=15;j>11;--j)r[j]=(1<<(j-12))&i?1:0; //最后4 变量是自由变量
仔细体会上面这2 句,如何产生 0 0 0 0 ----1111 的
----------------------------------高消+枚举-------poj1753-----------------------------------------------------------

#include <iostream>
#include <cstring>
#include <stdio.h>
using namespace std;
const int maxn=16;
int a[maxn][maxn+1],x[maxn],b[maxn][maxn+1];
int equ,var;
bool free_x[maxn+1]; // 判断是否是不确定的变元.
int free_num,ans=100000000;
int abs1(int num)
{
if (num>=0) return num;
else
return -1*num;
}
void Debug(void)
{
int i, j;
for (i = 0; i < equ; i++)
{
for (j = 0; j < var + 1; j++)
{
cout << a[i][j] << " ";
}
cout << endl;
}
cout << endl;
}
inline int gcd(int a, int b)
{
int t;
while (b != 0)
{
t = b;
b = a % b;

a = t;
}
return a;
}
inline int lcm(int a, int b)
{
return a * b / gcd(a, b);
}
int dfs(int p) //枚举自由解,只能取0-1,枚举完就回带,找到最小的
{
if (p<=free_num-1) //深入到了主对角线元素非0 的行了
{ //下面就是回带的代码啊
for(int i = free_num-1;i >= 0; --i)
{
int tmp = a[i][var] % 2;
for(int j = i+1;j < var; ++j) //x[i]取决于x[i+1]--x[var]啊,所以后面的解对前面的解有影
响。
if(a[i][j] != 0)
tmp = ( tmp - (a[i][j]*x[j])%2 + 2 ) % 2;
x[i] = (tmp/a[i][i]) % 2; //上面的正常解
} //回带完成了
//计算解元素为1 的个数;
int sum=0;
for(int i=0;i<var;i++) sum+=x[i];
if (ans>sum) ans=sum;
return 0;
}
x[p]=0;dfs(p-1);
x[p]=1;dfs(p-1);
}
void swap(int &a,int &b){int temp=a;a=b;b=temp;}
int Gauss_1()
{
int k,col = 0; //当前处理的列
for(k = 0;k < equ && col < var;++k,++col)

{
int max_r = k;
for(int i = k+1;i < equ; ++i)
if(a[i][col] > a[max_r][col])
max_r = i;
if(max_r != k)
{
for(int i = k;i < var + 1; ++i)
swap(a[k][i],a[max_r][i]);
}
if(a[k][col] == 0)
{
k--;
continue;
}
for(int i = k+1;i < equ; ++i)
{
if(a[i][col] != 0)
{
int LCM = lcm(a[i][col],a[k][col]);
int ta = LCM/a[i][col], tb = LCM/a[k][col];
if(a[i][col]*a[k][col] < 0)
tb = -tb;
for(int j = col;j < var + 1; ++j)
a[i][j] = ( (a[i][j]*ta)%2 - (a[k][j]*tb)%2 + 2 ) % 2; //a[i][j]只有0 和
1 两种状态
}
}
}
for(int i = k;i < equ; ++i)
if(a[i][col] != 0) return -1; // 无解返回 -1
//上述代码是消元的过程,消元完成
//Debug();
//唯一解或者无穷解,k<=var
//var-k==0 唯一解;var-k>0 无穷多解,自由解的个数=var-k
//下面这几行很重要,保证秩内每行主元非0,且按对角线顺序排列
for(int i = 0; i <equ; ++i)//每一行主元素化为非零

if(!a[i][i])
{
int j;
for(j = i+1;j<var;++j)
if(a[i][j])
break;
if(j == var)
break;
for(int k = 0;k < equ; ++k)
swap(a[k][i],a[k][j]);
}
// ----处理保证对角线主元非0 且顺序,完成
free_num=k;
if (var-k>0) { dfs(var-1); return ans;}
if (var-k==0)//唯一解时,poj1753 本题没唯一解,当题目具体操作给出后,系数矩阵已
经固定了!
{
//下面是回带求解,当无穷多解时,最后几行为0
for(int i = k-1;i >= 0; --i)
{
int tmp = a[i][var] % 2;
for(int j = i+1;j < var; ++j) //x[i]取决于x[i+1]--x[var]啊,所以后面的解对前面的解有影
响。
if(a[i][j] != 0)
tmp = ( tmp - (a[i][j]*x[j])%2 + 2 ) % 2;
//if (a[i][i]==0) x[i]=tmp; //最后的空行时,即无穷解得
//else
x[i] = (tmp/a[i][i]) % 2; //上面的正常解
}
int sum=0;
for(int i=0;i<var;i++) sum+=x[i];
return sum;

}
}
int main()
{
int k,free_num;
char c1[20];
memset(a,0,sizeof(a));
memset(x,0,sizeof(x));
ans=1000000000;
for (int i=0;i<4;i++)
{
cin>>c1;
//构造系数矩阵A
for (int j=0;j<4;j++)
{
k = 4*i+j;
a[k][k]=1;
if (i>0) a[k][k-4]=1; //上
if (i<3) a[k][k+4]=1; //下
if (j>0) a[k][k-1]=1; //左
if (j<3) a[k][k+1]=1; //右
if (c1[j]=='b')
a[k][maxn] = 1;
}
}
for(int i=0;i<16;i++)
for(int j=0;j<=16;j++)
b[i][j]=a[i][j];
for(int k=0;k<16;k++)
b[k][16]^=1;
equ=var=16;
int j1=Gauss_1();
int min1=ans;
for(int i=0;i<16;i++)
for(int j=0;j<=16;j++)

a[i][j]=b[i][j];
ans=100000000;
int j2=Gauss_1();
int min2=ans;
if (j1==-1&&j2==-1) cout<<"Impossible"<<endl;
else
cout<<min(ans,min1)<<endl;
// cout << "Hello world!" << endl;
return 0;
}
对于2947 和2065 我是用下面的模板过的
下是高斯消元+同余方程的模板
#define maxn 80
int equ,var,prime;
char st[80];
int aa[maxn][maxn],x[maxn];
inline int abs1(int x)
{
if (x>=0) return x;
else
return -1*x;
}
inline int gcd(int a, int b)
{
int t;
while (b != 0)
{
t = b;
b = a % b;
a = t;

a[i][j]=b[i][j];
ans=100000000;
int j2=Gauss_1();
int min2=ans;
if (j1==-1&&j2==-1) cout<<"Impossible"<<endl;
else
cout<<min(ans,min1)<<endl;
// cout << "Hello world!" << endl;
return 0;
}
对于2947 和2065 我是用下面的模板过的
下是高斯消元+同余方程的模板
#define maxn 80
int equ,var,prime;
char st[80];
int aa[maxn][maxn],x[maxn];
inline int abs1(int x)
{
if (x>=0) return x;
else
return -1*x;
}
inline int gcd(int a, int b)
{
int t;
while (b != 0)
{
t = b;
b = a % b;
a = t;

}
return a;
}
inline int lcm(int a, int b)
{
return a * b / gcd(a, b);
}
int extgcd(int a, int b, int & x, int & y){
if (b == 0) { x=1; y=0; return a; }
int d = extgcd(b, a % b, x, y);
int t = x; x = y; y = t - a / b * y;
return d;
}
int Gauss(){
int i,j,k;
int max_r , col , temp;
int LCM , GCD;
int ta,tb;
col = 0;
for(k=0 ; k<equ && col < var ; k++,col++)
{
max_r = k;
for(i=k+1 ; i<equ ; i++)
{ if(abs1(aa[i][col]) > abs1(aa[max_r][col]))max_r = i;}
if(max_r != k)
{ for(j=k ; j<var+1 ; j++)swap(aa[k][j],aa[max_r][j]);}
if(aa[k][col] == 0)
{ k--;continue;
}
for(i=k+1 ; i<equ ; i++)
{

if(aa[i][col] != 0)
{
LCM = lcm(abs1(aa[i][col]) , abs1(aa[k][col]));
ta = LCM/abs1(aa[i][col]) ;
tb = LCM/abs1(aa[k][col]);
if(aa[i][col] * aa[k][col] < 0)tb = -tb;
for(j=col ; j<var+1 ; j++)
{ aa[i][j] = (aa[i][j]*ta-aa[k][j]*tb) % prime;
}
}
}//for
}
for(i=var-1 ; i>=0 ; i--)
{
temp = aa[i][var];
for(j=i+1 ; j<var ; j++)
{ if(aa[i][j] != 0)temp =(temp - aa[i][j]*x[j]%prime) ;
}
temp = (temp%prime + prime) % prime;
GCD = extgcd(aa[i][i] , prime , x[i] , k);
x[i] = ( (x[i]*(temp/GCD) % prime) + prime) % prime;
}
return 0;
}
用以上的代码 很快把poj 2065 A 掉了
POJ 2947 高斯消元 解题报告
题目大意:有n 种装饰物,m 个已知条件,每个已知条件的描述如下:
p start end
a1,a2......ap (1<=ai<=n)
第一行表示从星期start 到星期end 一共生产了p 件装饰物(工作的天数为end-start+1+7*x,

加7*x 是因为它可能生产很多周),第二行表示这p 件装饰物的种类(可能出现相同的种类,
即ai=aj)。规定每件装饰物至少生产3 天,最多生产9 天。问每种装饰物需要生产的天数。
如果没有解,则输出“Inconsistent data.”,如果有多解,则输出“Multiple solutions.”,如果
只有唯一解,则输出每种装饰物需要生产的天数。
解题思路:高斯消元。设每种装饰物需要生产的天数为xi(1<=i<=n)。每一个条件就相当于
给定了一个方程式,假设生产1 类装饰物a1 件、2 类装饰物a2 件、i 类装饰物ai 件所花费
的天数为b,则可以列出下列方程:
a1*x1+a2*x2+...an*xn = b (mod 7)
这样一共可以列出m 个方程式,然后使用高斯消元来解此方程组即可。
#include <iostream>
#include <cstring>
#include <stdio.h>
using namespace std;
#define maxn 305
int equ,var,prime;
//char st[80];
char data[7][5]={"MON","TUE","WED","THU","FRI","SAT","SUN"};
int aa[maxn][maxn],x[maxn];
inline int abs1(int x)
{
if (x>=0) return x;
else
return -1*x;
}
inline int gcd(int a, int b)
{
int t;
while (b != 0)
{
t = b;

b = a % b;
a = t;
}
return a;
}
inline int lcm(int a, int b)
{
return a * b / gcd(a, b);
}
int extgcd(int a, int b, int & x, int & y){
if (b == 0) { x=1; y=0; return a; }
int d = extgcd(b, a % b, x, y);
int t = x; x = y; y = t - a / b * y;
return d;
}
int Gauss(){
int i,j,k;
int max_r , col , temp;
int LCM , GCD;
int ta,tb;
col = 0;
for(k=0 ; k<equ && col < var ; k++,col++)
{
max_r = k;
for(i=k+1 ; i<equ ; i++)
{ if(abs1(aa[i][col]) > abs1(aa[max_r][col]))max_r = i;}
if(max_r != k)
{ for(j=k ; j<var+1 ; j++)swap(aa[k][j],aa[max_r][j]);}
if(aa[k][col] == 0)
{ k--;continue;
}

for(i=k+1 ; i<equ ; i++)
{
if(aa[i][col] != 0)
{
LCM = lcm(abs1(aa[i][col]) , abs1(aa[k][col]));
ta = LCM/abs1(aa[i][col]) ;
tb = LCM/abs1(aa[k][col]);
if(aa[i][col] * aa[k][col] < 0)tb = -tb;
for(j=col ; j<var+1 ; j++)
{ aa[i][j] = (aa[i][j]*ta-aa[k][j]*tb) % prime;
aa[i][j]=(aa[i][j]%7+7)%7;
}
}
}//for
}
for(i=k;i<equ;i++)
{
if (aa[i][col]!=0) return -1;//无解
}
if (k<var) return var-k;// 无穷多解
for(i=var-1 ; i>=0 ; i--)
{
temp = aa[i][var];
for(j=i+1 ; j<var ; j++)
{ if(aa[i][j] != 0) temp =(temp - aa[i][j]*x[j]%prime) ;
//temp=temp-aa[i][j]*x[j];
}
temp = (temp%prime + prime) % prime;
GCD = extgcd(aa[i][i] , prime , x[i] , k);
x[i] = ( (x[i]*(temp/GCD) % prime) + prime) % prime;
// while(temp%aa[i][i])
// temp+=7;

//x[i]=temp/aa[/i][i];
//x[i]=(x[i]%7+7)%7;
while(x[i]<3) x[i]=x[i]+7;
//while(x[i]>9) x[i]=x[i]-7;
}
return 0;
}
//void init()
//{
// int n=var;
//}
int comp_1(char a[])
{
int j=0;
for(int i=0;i<7;i++)
if (strcmp(a,data[i])==0) j=i;
cout<<"s="<<j<<endl;
return j;
}
int main()
{
//`MON', `TUE', `WED', `THU', `FRI', `SAT' and `SUN'.
int m,n,k,typ;
int num1,num2;
char s1[5],s2[5];
prime=7;
while(scanf("%d%d",&m,&n))
{

if (m==0&&n==0) break;
var=m; //这个要注意,var!=equ 啊
equ=n;
//var=equ=m;
memset(aa,0,sizeof(aa));
memset(x,0,sizeof(x));
for(int i=0;i<n;i++)
{
scanf("%d",&k);
scanf("%s %s",s1,s2);
for(int i=0;i<7;i++)
{
if (strcmp(s1,data[i])==0)
num1=i;
if (strcmp(s2,data[i])==0)
num2=i;
}
int day=(num2-num1+1+7)%7;
// cout<<day<<endl;
for(int j=0;j<k;j++)
{
scanf("%d",&typ);
aa[i][typ-1]++;
aa[i][typ-1]%=7;
}
aa[i][m]=day;
}
int free_num=Gauss();
if (free_num==-1) cout<<"Inconsistent data."<<endl;
if (free_num>0) cout<<"Multiple solutions."<<endl;
if (free_num==0)
{

for(int i=0;i<var-1;i++)
cout<<x[i]<<" ";
cout<<x[var-1]<<endl;
}
}
//cout << "Hello world!" << endl;
return 0;
}
//本取余模板很好用,注意参数别犯低级错误
还有要补充的:
对于像1830 这样“连动“的开关的问题,采用逆向思维,以最终的灯列方程,不能以开始
的灯列方程;就是a[i]j[]的系数矩阵录入时,实际录入的是 a[j][i],就行了。
啥叫连动,就是1 个灯亮和不亮由很多灯控制,具体体会1830 题的文字描述,最后能把
HDU 的3364 和4200AC 掉,就算掌握“连动“了。
作业:把这9 个题都搞定,并尝试 同余的模板能用开始的那个模板来自己改写吗?
终极目标:举1 反3,掌握求解这类问题的本质,对于打亚洲赛的同学,要会使用double
型的高斯消元(矩阵值是整数,但解是双精度的),同时要能使用高斯+高精度AC 掉2008
亚洲哈尔滨的那道纯高消题,这是终极目标。
高消的考试1 周后进行!4 道简单题。
陈宇 2012/8/31

隔离型全桥LLC谐振变化器建模及参数设计资料【仿真+设计报告+计算书】 内容概要:本文档系统性地提供了隔离型全桥LLC谐振变换器的建模、仿真与参数设计全套技术资料,涵盖Simulink/Plecs仿真模型、详细设计报告及Mathcad计算书,内容涉及开环与闭环控制、软启动过程、恒压恒流双闭环竞争控制等多种工况。资料还拓展至多相交错LLC、双向CLLC拓扑以及V2G(Vehicle-to-Grid)电动汽车充放电等前沿应用场景,并融合状态估计算法(如卡尔曼滤波、扩展卡尔曼滤波、粒子滤波)与神经网络技术进行系统性能优化,配套PPT说明与高水平EI期刊复现案例,为电力电子领域的科研与工程设计提供完整的技术支撑; 适合人群:适用于电力电子、电气工程及其自动化等相关专业的高校研究生、科研人员,以及从事高频DC-DC变换器、新能源电源系统开发的工程师,具备扎实电路理论基础和Matlab/Simulink仿真能力者尤佳; 使用场景及目标:①支撑LLC谐振变换器相关的科研课题、学位论文或项目开发;②开展高频高效电源的参数设计、效率优化与动态响应分析;③学习并复现高水平期刊中先进的控制策略,如变频控制、混合移相控制及智能优化算法;④掌握Simulink/Matlab在电力电子系统建模、控制算法实现与状态估计中的综合应用; 阅读建议:建议结合仿真模型、Mathcad计算书与设计报告三位一体同步研习,重点理解主电路参数设计与闭环控制逻辑之间的耦合关系,优先运行典型算例并调试关键模块,有条件者可进一步推进至硬件原型验证,并积极探索状态估计与人工智能算法在电力系统动态建模中的融合应用。 立即下载

相关推荐

标准材质转物理材质 对应脚本:标准转物理材质转x.ms 一、插件用途 将 3ds Max 场景中的 StandardMaterial 标准材质转换为 PhysicalMaterial 物理材质

标准材质转物理材质 对应脚本:标准转物理材质转x.ms 一、插件用途 将 3ds Max 场景中的 StandardMaterial 标准材质转换为 PhysicalMaterial 物理材质,并递归处理 Multi/Sub 多维子材质及 Blend 混合材质中的标准材质。 二、转换内容 脚本尝试进行以下参数映射: - 漫反射颜色 → Physical Material 基础颜色。 - 漫反射贴图及启用状态 → 基础颜色贴图。 - 凹凸贴图、启用状态及强度 → 物理材质凹凸槽;强度会按脚本比例换算。 - Opacity 贴图 → 物理材质透明颜色贴图。 - 标准材质自发光颜色和强度 → 物理材质发光颜色和发光强度。 - 反射贴图强度 → 粗糙度的反向换算。 - Glossiness → Metalness 数值换算。 三、使用方法 1. 在 3ds Max 中运行脚本。 2. 出现“赵山河材质转换”小窗口。 3. 点击“标准材质转物理材质”。 4. 脚本扫描整个场景的材质库,并将场景物体所使用的标准材质转换为物理材质。 5. 转换完成后刷新视口。 四、处理范围 - 不是只处理当前选择对象,而是扫描整个场景的材质库。 - 对 Multi/Sub 材质递归转换其中的标准材质子项。 - 对 Blend 材质递归转换 map1、map2 中的材质。 - 非 StandardMaterial 的材质会按脚本逻辑保留,不会强制全部转成 PhysicalMaterial。 五、注意事项 - 这是参数近似转换,不是渲染结果完全一致的材质转换。 - 标准材质中的高光、反射、透明度、特殊贴图和高级参数不一定有一一对应关系。 - 脚本把 Glossiness 映射到 Metalness,属于

东北林业大学OJ题目3

军训 Problem:103 Time Limit:1000ms Memory Limit:65536K Description 军训真累啊,但毕竟对我们的意志是一种考验。教官在军训时,碰到这样一个问题,N名同学,排成一排,有多少中排列方法?听说你是林大最聪明的人,请你帮他解决这个问题吧? Input 输入数据有多组,每组1行,即N,代表学生数,其中1<=N<=15. Output 输出N个同学的排列方法数对int的取模,每个输出占1行,记得输出要换行啊! Sample Input 1 2 3

paimonL的博客 570

一篇关于轴承故障诊断的综述

在设备的故障检测中,有约30%-40%的设备故障是由轴承故障引起的,因此本文将列举有关检测轴承故障使用到的相关数据集,模型和算法。 数据集 现有的数据集,普遍由固定在电机马达上的两个震动检测器获得,并根据需要,分离震动数据在时域和频域上的特征以供网络模型学习。 不同的数据集,区别在于,检测的马达转速不同,环境不同,取样频率不同,一段样本的时长不同等等 (1)Case Western Reserve University (CWRU) Dataset 该数据集拥有多种数据,测量的时候,通过改变轴承.

weixin_42036144的博客 2万+

东北林业大学oj1025 又是指针

简单的题

北门的智慧 1777

从帧结构到数据解析:深入理解CJ/T 188 MBUS水表通信协议

本文深入解析CJ/T 188 MBUS水表通信协议,从帧结构到数据解析提供完整指南。通过典型报文示例和实战案例,详细讲解地址域、控制码、数据标识符(DI)等关键字段的解析技巧,并分享校验算法与常见错误排查方法,帮助开发者快速掌握MBUS协议在水表通信中的应用。

weixin_28710999的博客 421

STM32F103C8T6实战:手把手教你搭建智能火灾报警系统(附MQ-2传感器调试技巧)

本文详细介绍了基于STM32F103C8T6单片机和MQ-2烟雾传感器的智能火灾报警系统搭建过程。从硬件选型、电路设计到软件开发,提供全面的实战指导,特别包含MQ-2传感器调试技巧,帮助开发者快速实现稳定可靠的智能火灾监控系统。

year5的博客 213

[高斯消元] poj 1222 EXTENDED LIGHTS OUT

题目大意:给你一个5*6的矩阵,矩阵里每一个单元都有一个灯和一个开关,如果按下此开关,那么开关所在位置的那个灯和开关前后左右的灯的状态都会改变(即由亮到不亮或由不亮到亮)。给你一个初始的灯的状态,问怎样控制每一个开关使得所有的灯最后全部熄灭(此题保证有唯一解)。 解题思路:高斯消元。很显然每个灯最多只需要按1下(因为按两下和没有按是一个效果)。我们可以定义30和未知数x0、x1.

Enmity_Dark 960

Arcgis填补栅格空缺值Nodata

Arcgis填补栅格空缺值Nodata

pass17的博客 1万+

POJ1222 EXTENDED LIGHTS OUT 高斯消元

题目链接:http://poj.org/problem?id=1222 题目大意:给你一个5*6 的矩阵,矩阵里每一个单元都有一个灯和一个开关,如果按下此开关,那么开关所在位置的那个灯和开关前后左右的灯的状态都会改变(即由亮到不亮或由不亮到亮)。给你一个初始的灯的状态,问怎样控制每一个开关使得所有的灯最后全部熄灭(此题保证有唯一解)。 分析:高斯消元。很显然每个灯最多只需要按1

AC_Gibson的专栏 552

LeRobot SO-ARM100 学习笔记(2) diffusion module

对 lerobot 中的 diffusion policy 进行基本的代码阅读

mikhailbran的博客 1586

把 ABAP 选择屏幕 Selection Screen 打造成可维护的交互面板:常用屏幕元素与动态控制全解析

本文详细介绍了ABAP报表中Selection Screen的设计技巧,包括空行(SKIP)、横线(ULINE)、注释(COMMENT)等基础元素的使用方法,以及如何通过MODIF ID实现动态界面调整。重点讲解了行内布局(BEGIN OF LINE)、按钮(PUSHBUTTON)和区块(BLOCK)等高级功能,帮助开发者将选择屏幕从"能用"提升到"好用、易扩展、可维护"的水平。文章还分享了项目实践中的命名规范和分组策略,特别适合需要优化ABAP报表用户体验的开发人员

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 331

POJ - 1222 EXTENDED LIGHTS OUT 高斯消元法

中文描述: Description 给你一个5*6的矩阵,矩阵里每一个单元都有一个灯和一个开关,如果按下此开关,那么开关所在位置的 那个灯和开关前后左右的灯的状态都会改变 (即由亮到不亮或由不亮到亮)。给你一个初始的灯的状态, 问怎样控制每一个开关使得所有的灯最后全部熄灭。 Input 输入第一行整数N,代表有N组测试用例,每一组测试用例是一个5*6的矩阵,在5*6...

weixin_30716141的博客 199

图神经网络在金融风险传播分析中的应用

《图神经网络在金融风险传播分析中的应用》 摘要 本文旨在探讨图神经网络(Graph Neural Networks, GNN)在金融风险传播分析中的应用。首先,本文简要介绍了图神经网络的基本概念、发展历史以及其在各类应用场景中的重要性。接着,详细介绍了图神经网络的核心算法,包括图卷积神经网

AI天才研究院 1279

poj1222

EXTENDED LIGHTS OUT Description In an extended version of the game Lights Out, is a puzzle with 5 rows of 6 buttons each (the actual puzzle has 5 rows of 5 buttons each). Each button has a light

◆◇丶生如夏花。谁来订阅我的悲伤 548

NTscan扫描工具

ntscan是一个扫描器,可以扫描没有密码和弱密码的共享,先到配置文件中填写猜测的用户名和密码,扫描过程中右侧出现的是扫描日志。

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

poj1222 EXTENDED LIGHTS OUT 【高斯消元】

链接:http://poj.org/problem?id=1222 题意:给你一个5*6的矩阵,每个矩阵里有一个灯,用01表示开关状态,没按下一个灯的开关,它与他四周的灯的状态改变,问怎么操作使得灯全都关闭灭。 分析:经典的开关问题,一共有30个灯,用x0~x29表示,每个灯对应一个方程:x(i*6+j)+x(i*6+j+1)+x(i*6+j-1)+x((i+1)*6+j)+x((i-1)*6

Fb_by 377

ssm框架搭建

这个是一个在idea上成功跑起来的ssm框架项目,保存在这里方便以后使用直接下载

(林大oj1276)

林大oj1276 感谢冯学长的指点 题目地址:https://acm.nefu.edu.cn/JudgeOnline/problemShow.php?problem_id=1276 本题思路是:先积分成等比数列,利用等比数列性质求和,再求导还原。 用到了 —— 费马小定理、快速幂、快速乘(防止直接乘爆longlong,用加代替乘,边加边取模)、大数字符读入处理、还有逆元。 经过积分 求和 再求...

呼吸 486

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

POJ 1222 EXTENDED LIGHTS OUT

Description In an extended version of the game Lights Out, is a puzzle with 5 rows of 6 buttons each (the actual puzzle has 5 rows of 5 buttons each). Each button has a light. When a button is presse

jjs98 683

[POJ1222]EXTENDED LIGHTS OUT(高斯消元)

题目: 我是超链接 题意: 给出一些01状态,按动一个按键与其相邻的4个和它本身的状态会取反,求使其全部变成0的按动方案。 题解: 我记得以前摩尔庄园有一个这样的游戏,而我当时只知道瞎摁。 可以发现灯的开关状态只和按下开关次数的奇偶性有关,那么可以构造异或方程组的模型。把每个开关按或没按设成未知量xi,如果按了就赋值为1,没按就赋值为0,那么可以发现某个灯状态改没改变取决于它自己的...

薇小薇 367

POJ 1222 熄灯问题

    题目给出一个5*6的矩阵:0表示灯是灭着的,1表示灯是开着的,要求给出每盏灯的开关情况,让所有灯灭掉。开关规则:当按下一盏灯的开关,它上下左右四盏灯也会开关(亮的灭掉,暗的亮起),边角和边缘影响的灯会有不同。     该如何确定是否按下每盏灯的开关呢?最简单就是用穷举。每盏灯有两种情况,5*6共30盏灯,一共2^30种可能。太多了,应该尽可能地“减枝”,让穷举范围尽可能小,以不至于超时。...

RoaringPig的博客 368

林大378

点击打开链接 #include #include #include using namespace std; int main(int argc, char *argv[]) { int a,b,t,add=-1; while(~scanf("%d",&a)) { int test[a]; for(int i=0;i<a;i++)

謎のかれ 2783

翻转格子poj 1753

/*poj 1753 题意:有4*4的正方形,每个格子要么是黑色,要么是白色,当把一个格子的颜色改变(黑->白或者白->黑)时, 其周围上下左右(如果存在的话)的格子的颜色也被反转,问至少反转几个格子可以使4*4的正方形变 为纯白或者纯黑? Sample Input bwwb bbwb bwwb bwww Sample Output 4*/ #include #include char m

zhulingyan1018的博客 755

POJ1222 EXTENDED LIGHTS OUT

EXTENDED LIGHTS OUTTime Limit: 1000MS Memory Limit: 10000K Total Submissions: 8006 Accepted: 5207 DescriptionIn an extended version of the game Lights Out, is a puzzle with 5 rows of 6 butto

纯牛奶 464

林大1506

#include &lt;iostream&gt; #include &lt;cstdio&gt; #include &lt;cstring&gt; using namespace std; const int N=1e6+5; int sum[4*N],lsum[4*N],rsum[4*N],a[N]; int n,m; void pushdown(int k,int l,int r) { ...

Gragon_sgirlfriend的博客 284

POJ-1222 EXTENDED LIGHTS OUT(高斯消元)

题意: 给你一个5*6的矩阵,每个点上都有一个灯,按下f[i][j]的按钮,f[i][j]位置的灯的状态会改变,它上下左右的灯的状态也会改变(开变关,关变开)。 现在给出这个矩阵的初始状态,输出按下哪些按钮,使所有的灯都关闭。 做法: 利用高斯消元解异或方程组。 用x[i][j]表示第i行第j列的灯是否被按下 x[i][j] ^  x[i+1][j] ^  x[i-1][j]

GoldMoon 1618
上一篇: USACO section 2.2 Party Lamps
下一篇: pku 1681 Painter's Problem(高斯消元)
剑不飞
博客等级 码龄15年 86粉丝 505原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值