ps.改了标题
魔板
-
思路:按序消除变量,用当前行(i)【行i消元素】,消后面的每一行的i元素
最后按逆序回代值
注意若有i~n行i元素系数都为0说明没有唯一解(其余x的解跟i元素有关),没事,跳过i元素不跳过i行继续算,最后判断系数全为0的情况下值是否为0 -
代码:
#include<bits/stdc++.h>
using namespace std;
const int N=105;
double a[N][N],eps=1e-8;
int main() {
int n;
scanf("%d",&n);
for(int i=0;i<n;i++) for(int j=0;j<=n;j++)scanf("%lf",&a[i][j]);
//校园
for(int i=0;i<n;i++) { //j:当前的变量,i:第几行
int r=i;
for(int k=i+1;k<n;k++)
if(fabs(a[k][i])>fabs(a[r][i])) r=k;
if(fabs(a[r][i])<eps) {printf("No Solution");return 0;}
if(r!=i) {
for(int j=0;j<=n;j++) swap(a[r][j],a[i][j]);
}
for(int k=i+1;k<n;k++) {
double s=a[k][i]/a[i][i];
for(int l=0;l<=n;l++) {
a[k][l]-=a[i][l]*s;
}
}
}
//回代
for(int i=n-1;i>=0;i--) {
a[i][n]=a[i][n]/a[i][i];
for(int j=0;j<i;j++) {
a[j][n]-=a[j][i]*a[i][n];
}
}
for(int i=0;i<n;i++) printf("%.2lf\n",a[i][n]);
return 0;
}
补充几道习题。
SETI
- 思路:一道版题,但因为我上课听的不够认真而误解。
同余方程下成立直接最小正整数成立即可Qwq
那就很水了,不贴代码
球形空间产生器
- 思路:我不知道为什么可以相邻的来搞在一起就会对。总之假如这样,用数学推导就很容易了。
中央暖气
- 思路:文字游戏,然后引进了一类新的xor类型的高斯消元,其实还比浮点数好写些.
- 代码(xor)
//我是傻逼 我是傻逼 我是傻逼
#include<stdio.h>
#include<bits/stdc++.h>
using namespace std;
const int N=305;
int n;
bool a[N][N];
bool Guass() {
for(int i=1;i<=n;i++) {
int r=i;
while(!a[r][i]&&r<n) r++;
if(!a[r][i]) {return false;}
if(r!=i) {
for(int j=1;j<=n+1;j++) swap(a[r][j],a[i][j]);
}
for(int j=i+1;j<=n;j++) {
if(a[j][i]) {
for(int k=1;k<=n+1;k++) a[j][k]^=a[i][k];
}
}
}
for(int i=n;i;i--) {
for(int j=1;j<i;j++) {
a[j][n+1]^=a[j][i]*a[i][n+1];
}
}
for(int i=1;i<=n;i++) {
if(a[i][n+1]) printf("%d ",i);
}
return true;
}
int main() {
scanf("%d",&n);
for(int i=1;i<=n;i++) {
int x;
while(1) {
scanf("%d",&x);
if(x==-1) break;
a[x][i]=1;
}
}
for(int i=1;i<=n;i++) a[i][n+1]=1;
if(!Guass())printf("No solution");
return 0;
}
ps.之所以sb因为没初始化调了30min
开关问题
- 思路:这道考察对自由元的理解:
1.出现自由元只会lead to two sides无解或者多解
2.若多解,无论自由元取值什么值,非自由元依旧有解。(即自由元与非自由元无明显联系)
然后,这道题就答案:2^自由元的个数
手机游戏
-
思路:这个也写了好久,就很烦。(震惊!原因竟然是for循环没有枚举到0,而是枚举到了1)
思路就是二进制枚举自由元选取状态,一个一个带回取消元。 -
代码:
#include<stdio.h>
#include<bits/stdc++.h>
using namespace std;
const int N=2005;
char s[N][N];
bool is_free[N],tmp[N],a[N][N];
int lst,b[N][N],n,Free[N],num,dir[7][2]={{0,0},{1,0},{-1,0},{0,-1},{0,1}};
bool Goose() {
int i,j;
for(i=0,j=0;i<n&&j<n;) {
int r=i;
while(!a[r][j]&&r<=n) r++;
if(r>n) {is_free[j]=1;Free[num++]=j++;continue;}
if(r!=i) for(int k=0;k<=n;k++)swap(a[i][k],a[r][k]);
for(int k=i+1;k<n;k++) {
if(a[k][j]) {
for(int l=0;l<=n;l++) a[k][l]^=a[i][l];
}
}
i++,j++;
}
for(int k=i;k<n;k++) if(a[k][n]){return false;}
lst=i;
return true;
}
int Freedom() {
int ans=1e9;
for(int s=0;s<(1<<num);s++) {
for(int i=0;i<n;i++) tmp[i]=a[i][n];
int res=0;
for(int i=0;i<num;i++) {
if((1<<i)&s) {
res++;
for(int k=0;k<n;k++) {
tmp[k]^=a[k][Free[i]];
}
}
}
int i=lst-1;
for(int j=n-1;j>=0;j--) {
if(is_free[j])continue;
res+=tmp[i];
for(int k=0;k<i;k++) {
tmp[k]^=tmp[i]*a[k][j];
}
i--;
}
ans=min(ans,res);
}
return ans;
}
int main() {
int q;
scanf("%d",&q);
for(int i=0;i<q;i++) scanf("%s",s[i]);
for(int i=0;i<q;i++)for(int j=0;j<q;j++)b[i][j]=n++;
for(int i=0;i<q;i++)for(int j=0;j<q;j++)a[b[i][j]][n]=(s[i][j]=='w');
for(int i=0;i<q;i++)for(int j=0;j<q;j++) {
for(int d=0;d<5;d++) {
int x=i+dir[d][0],y=j+dir[d][1];
if(x<0||y<0||x>=q||y>=q)continue;
a[b[x][y]][b[i][j]]=1;
}
}
if(!Goose()) printf("inf");
else {
int ans=Freedom();
printf("%d",ans);
}
return 0;
}
[USACO3.2.4】Feed Ratios饲料调配
-
思路:告诉我们两件事
1.若多了一个变量别急着看题解(我很后悔),直接暴力枚举这个变量即可。
2.有毒瘤出题人卡高斯消元弄出了x.9999..这种数据,然后fabs((int)x.9999-x.9999)=1然后就挂了
解决方法就是一切浮点数+eps(越小越好) -
代码:
//这题的浮点数误差剧坑
//(int)4.9999999...=4
#include<bits/stdc++.h>
using namespace std;
int b[5][5];
double a[5][5],eps=1e-14;
bool Guass() {
for(int i=1;i<=3;i++) {
int r=i;
for(int k=i+1;k<=3;k++)
if(fabs(a[k][i])>fabs(a[r][i])) r=k;
if(fabs(a[r][i])<eps) {return false;}
if(r!=i) {
for(int j=1;j<=4;j++) swap(a[r][j],a[i][j]);
}
for(int k=i+1;k<=3;k++) {
double s=a[k][i]/a[i][i];
for(int l=1;l<=4;l++) {
a[k][l]-=a[i][l]*s;
}
}
}
for(int i=3;i>=1;i--) {
a[i][4]=a[i][4]/a[i][i];
for(int j=1;j<i;j++) {
a[j][4]-=a[j][i]*a[i][4];
}
}
return true;
}
int main() {
int x,y,z,X,Y,Z;
scanf("%d%d%d",&x,&y,&z);
for(int i=1;i<=3;i++) {
for(int j=1;j<=3;j++) {
scanf("%d",&b[i][j]);
}
}
for(int k=1;k<=100;k++) {
for(int j=1;j<=3;j++) {
for(int i=1;i<=3;i++) {
a[j][i]=b[i][j];
}
}
X=x*k,Y=y*k,Z=z*k;
a[1][4]=X,a[2][4]=Y,a[3][4]=Z;
if(Guass()) {
bool flag=true;
for(int i=1;i<=3;i++) {
if(a[i][4]-(int)a[i][4]>eps&&(int)(a[i][4]+eps)==(int)a[i][4]||a[i][4]+eps<0) {flag=false;break;}
}
if(flag) {
for(int i=1;i<=3;i++) printf("%d ",(int)(a[i][4]+eps));
printf("%d",k);
return 0;
}
}
}
printf("NONE");
return 0;
}
外星千足虫
- 思路:在每次找到非零行时取max,注意用bitset优化一个O(W)
注意bitset是一个二进制,只能整体运算,但可以取单体的值。 - 代码:
#include<bits/stdc++.h>
using namespace std;
const int N=2e3+5;
bitset<N> a[N];
char s[N];
int k,n,m,b[N];
void Guass() {
for(int i=0;i<n;i++) {
int r=i;
while(r<m&&!a[r][i]) r++;
if(r==m) {printf("Cannot Determine");exit(0);}
k=max(k,r);
if(i!=r) swap(a[i],a[r]),swap(b[i],b[r]);
for(int j=i+1;j<m;j++) {
if(a[j][i]) {
a[j]^=a[i],b[j]^=b[i];
}
}
}
for(int i=n-1;i>=0;i--) {
for(int j=0;j<i;j++) {
b[j]^=b[i]*a[j][i];
}
}
}
int main() {
scanf("%d%d",&n,&m);
for(int i=0;i<m;i++) {
int x;
scanf("%s%d",s,&x);
for(int j=0;j<n;j++) a[i][j]=s[j]-'0';
b[i]=x;
}
Guass();
printf("%d\n",k+1);
for(int i=0;i<n;i++) {
if(b[i]) printf("?y7M#\n");
else printf("Earth\n");
}
return 0;
}
【CQOI2014】和谐矩阵【毒瘤版】
一切的源头就是NKOJ男鞋的spj,然后就进阶成了一道思维题(字典)
- 思路:或许其它人都是用的暴力+贪心,但是我是直接贪心(没有任何暴力,跑得飞快)
首先,我们容易想到倒着消元,这样越前面的数只要不是一定确定,被定为自由元的优先级就更高
所以回代的顺序就是顺着的。
其次,自由元的性质是该自由元后面的行都为0,而我们是倒着消元的,因此自由元不影响前面的取值(字典序),所以我们直接将所有自由元取0。
你会发现矩阵全零了!!!
最后,我们贪心:将最后一个自由元赋为1,然后顺势回代,跟原高斯消元的代码相近,然后就AC啦。
贪心就用“其次……”这个性质非常的好证明。 - 代码:
1485 B
源代码
#include<stdio.h>
#include<bits/stdc++.h>
using namespace std;
const int N=2005;
int a[N][N];
bool is_free[N];
int h,l,fst,b[N][N],n,cnt=0,dir[7][2]={{0,0},{1,0},{-1,0},{0,1},{0,-1}};
void Print() {
for(int i=0;i<n;i++) {
if(i&&i%l==0) printf("\n");
if(i==fst) printf("1 ");
else if(is_free[i]) printf("0 ");
else printf("%d ",a[i][n]);
}
}
void Guass() {
int i,j,r;
for(i=n-1,j=n-1;i>=0&&j>=0;) {
r=i;
while(r>=0&&!a[r][j]) {r--;}
if(r<0) {if(!fst)fst=j;is_free[j]=1,--j;continue;}
if(i!=r) swap(a[i],a[r]);
for(int k=i-1;k>=0;k--) {
if(a[k][j]) {
for(int l=0;l<=n;l++) a[k][l]^=a[i][l];
}
}
--i,--j;
}
// Print();
// Print2();
i++; j++;
while(i<n&&j<n) {
// printf("%d %d\n",i,j);
if(fst==j) {
for(int k=i;k<n;k++) if(a[k][j])a[k][n]^=1;
j++; continue;
}
else if(is_free[j]) {j++;continue;}
else if(a[i][n]) {
for(int k=i+1;k<n;k++) {
a[k][n]^=a[i][n]*a[k][j];
}
}
i++,j++;
// Print();
// Print2();
}
}
int main() {
scanf("%d%d",&h,&l);
for(int i=1;i<=h;i++) for(int j=1;j<=l;j++) b[i][j]=cnt++;
for(int i=1;i<=h;i++) for(int j=1;j<=l;j++) {
for(int t=0;t<5;t++) {
int x=i+dir[t][0],y=j+dir[t][1];
if(x<1||y<1||x>h||y>l) continue;
a[b[i][j]][b[x][y]]=1;
}
}
n=h*l;
Guass();
Print();
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· winform 绘制太阳,地球,月球 运作规律
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人