2025-12-22 hetao1733837的笔记

2025-12-22 hetao1733837的笔记

我决定不浪费好题了。直接抄的高消没啥意义,所以,应当借助 AI 学习。

普通高消我认为我已经会了,所以,应该去写几道题,熟悉一下板子。
DeepSeek 在《算法竞赛》题单里挑了下面这题。

普通方程组

LG4035 [JSOI2008] 球形空间产生器

原题链接:[JSOI2008] 球形空间产生器

分析

我似乎并不见得能列出方程,但是,我有一种感觉就是,要求的坐标到这些点的距离都是相等的。

呃......好像有方程了,但并非是一次的。即我们设球心坐标 ( p a n s , 1 , p a n s , 2 , p a n s , 3 , ... , p a n s , n ) (p_{ans,1}, p_{ans,2},p_{ans,3},\dots,p_{ans,n}) (pans,1,pans,2,pans,3,...,pans,n),则
( p 1 , 1 − p a n s , 1 ) 2 + ( p 1 , 2 − p a n s , 2 ) 2 + ⋯ + ( p 1 , n − p a n s , n ) = ( p 1 , 1 − p a n s , 1 ) 2 + ( p 1 , 2 − p a n s , 2 ) 2 + ⋯ + ( p 1 , n − p a n s , n ) = ( p 2 , 1 − p a n s , 1 ) 2 + ( p 2 , 2 − p a n s , 2 ) 2 + ⋯ + ( p 2 , n − p a n s , n ) ... = ( p n + 1 , 1 − p a n s , 1 ) 2 + ( p n + 1 , 2 − p a n s , 2 ) 2 + ⋯ + ( p n + 1 , n − p a n s , n ) (p_{1, 1}-p_{ans,1})^2+(p_{1, 2}-p_{ans,2})^2+\dots +(p_{1,n}-p_{ans,n}) \\=(p_{1, 1}-p_{ans,1})^2+(p_{1, 2}-p_{ans,2})^2+\dots +(p_{1,n}-p_{ans,n}) \\=(p_{2, 1}-p_{ans,1})^2+(p_{2, 2}-p_{ans,2})^2+\dots +(p_{2,n}-p_{ans,n}) \\\dots \\=(p_{n+1, 1}-p_{ans,1})^2+(p_{n+1, 2}-p_{ans,2})^2+\dots +(p_{n+1,n}-p_{ans,n}) (p1,1−pans,1)2+(p1,2−pans,2)2+⋯+(p1,n−pans,n)=(p1,1−pans,1)2+(p1,2−pans,2)2+⋯+(p1,n−pans,n)=(p2,1−pans,1)2+(p2,2−pans,2)2+⋯+(p2,n−pans,n)...=(pn+1,1−pans,1)2+(pn+1,2−pans,2)2+⋯+(pn+1,n−pans,n)

呃,这对吗?呃, p p p 数组似乎是已知的,则,似乎可以得到关于 p a n s , 1 , p a n s , 2 , p a n s , 3 , ... , p a n s , n p_{ans,1}, p_{ans,2},p_{ans,3},\dots,p_{ans,n} pans,1,pans,2,pans,3,...,pans,n 的方程,然后,暴力相减即可消去 ( p a n s , k ) 2 (p_{ans,k})^2 (pans,k)2,移项即可将常数放到右边。那就做完了?卧槽,我能写蓝了?

卧槽了,居然有提示/ll

这么贴心,居然给了 n + 1 n+1 n+1 组已知位置,这样就好写很多了。

正解

cpp 复制代码
#include <bits/stdc++.h>
using namespace std;
const int N = 15;
const double eps = 1e-8;
int n;
double a[N][N]; 
double p[N][N];
int main() {
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
    cin >> n;
    for (int i = 1; i <= n + 1; i++){
        for (int j = 1; j <= n; j++){
            cin >> p[i][j];
        }
    }
    for (int i = 1; i <= n; i++){ 
        double sum1 = 0.0, sum2 = 0.0;
        for (int j = 1; j <= n; j++){
            a[i][j] = 2.0 * (p[i + 1][j] - p[1][j]); 
            sum1 += p[i + 1][j] * p[i + 1][j];
            sum2 += p[1][j] * p[1][j];
        }
        a[i][n + 1] = sum1 - sum2;  
    }
    for (int i = 1; i <= n; i++){
        int maxn = i;
        for (int j = i + 1; j <= n; j++){
            if (fabs(a[j][i]) > fabs(a[maxn][i])){
                maxn = j;
            }
        }
        for (int j = 1; j <= n + 1; j++){
            swap(a[i][j], a[maxn][j]);
        }
        double div = a[i][i];
        for (int j = i; j <= n + 1; j++){
            a[i][j] /= div;
        }
        for (int j = 1; j <= n; j++){
            if (j != i){
                double mul = a[j][i];
                for (int k = i; k <= n + 1; k++){
                    a[j][k] -= a[i][k] * mul;
                }
            }
        }
    }
    for (int i = 1; i <= n; i++){
        cout << fixed << setprecision(3) << a[i][n + 1] << " ";
    }
}

呃,依然没调出来......

不说了,现在开始,认真学习高消求取异或方程组

异或方程组/模 2 线性方程组

mhh 咋这么强,这都知道!

那么,异或方程就相当于模2方程,则加减都是异或,乘是按位与,没了......呃......

需要强调的是,系数、未知数、方程右边的数都应给 ∈ { 0 , 1 } \in \{0,1\} ∈{0,1}。

LG2447 [SDOI2010] 外星千足虫

原题链接:[SDOI2010] 外星千足虫

分析

废话不多说,直接上题目。

嗯,确实很板,但是,我并非会做啊......喔,这个电脑用暗色模式+金黄色字体真得漂亮!

呃,由于千足虫足数并不重要,只需要知道是奇数还是偶数即可,不妨看作 0 / 1 0/1 0/1,但是吧,又有了一个问题就是怎么判定到那一组可以判断全部......难道是所有位置都出现了?似乎不太对。

这个方程是极其简单的,题目已经喂到嘴边了。花花,你的线性基害人不浅/ll

呃,算是讲明白了,也就是说,这题的坑点在于我们怎么求这个尽可能小的 k k k,在高消的过程中,我们尽可能选取编号小的消,消不掉则此时有多组解,继续往后添加即可,由于 O ( n 3 ) O(n^3) O(n3) 跑不下,故使用 bitset

正解

cpp 复制代码
#include <bits/stdc++.h>
using namespace std;
const int N = 1005;
string s;
bitset<N> mat[N << 1];
int gauss(int n, int m){
	int k = -1;
	for (int i = 1; i <= n; i++){
		int cur = i;
		while (cur <= m && !mat[cur].test(i))
			cur++;
		if (cur > m)
			return 0;
		k = max(k, cur);
		if (cur != i)
			swap(mat[cur], mat[i]);
		for (int j = 1; j <= m; j++){
			if (i != j && mat[j].test(i))
				mat[j] ^= mat[i];
		}
	}
	return k;
}
int n, m;
int main(){
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	cin >> n >> m;
	for (int i = 1; i <= m; i++){
		int val;
		cin >> s >> val;
		for (int j = 0; j < n; j++){
			if (s[j] == '1')
				mat[i].set(j + 1, 1);
			else
				mat[i].set(j + 1, 0);
		}
		mat[i].set(0, val);
	}
	int k = gauss(n, m);
	if (k){
		cout << k << '\n';
		for (int i = 1; i <= n; i++){
			if (mat[i].test(0))
				cout << "?y7M#" << '\n';
			else
				cout << "Earth" << '\n';
		}
	}
	else
		cout << "Cannot Determine";
}

呃,我并非很理解吧......

模线性方程组

POJ2947 Widget Factory

原题链接:Widget Factory

分析

显然,昨天被我一眼盯出来是取模了,方程其实很好列,就是他做的那些东西前面系数定为 1 1 1,否则为 0 0 0,等式右边就是总天数对 7 7 7 取模后的天数。等一下,要是我周日入职,周一离职怎么办?一样吗?我决定学习一下题解。

都是啥啊?

正解

cpp 复制代码
#include<iostream>
#include<string>
#include<cstdio>
#include<cstring>
#include<map>
using namespace std;
map<string,int> data;
const int MAXN = 350;
int a[MAXN][MAXN];
int b[MAXN],ans[MAXN];
int n,m,x,num;
string s,e;
void init(){
	data["MON"] = 1; data["TUE"] = 2;
	data["WED"] = 3; data["THU"] = 4;
	data["FRI"] = 5; data["SAT"] = 6;
	data["SUM"] = 7;
}
void solve(){
	int i = 1,j = 1,l,x,y;
	while(i <= m && j <= n){
		for(l = i;l <= m;l++){
			if(a[l][j])	break;
		}
		if(l > m){
			j++; 
			continue;
		}
		for(int k = n;k;k--) swap(a[l][k],a[i][k]);
		swap(b[l],b[i]);
		x = a[i][j];
		for(l = i+1;l <= m;l++){
			y = a[l][j];
			for(int k = j;k <= n;k++){
				a[l][k] = (a[l][k]*x - a[i][k]*y)%7;
			}
			b[l] = (b[l]*x - b[i]*y)%7;
		}
		i++,j++;
	}
	for(l = i;l <= m;l++)	
		if(b[l]){ puts("Inconsistent data."); return; }
	if(i != j || j < n){ puts("Multiple solutions."); return;}
	int k;
	for(i--,j--;i;i--,j--)
	{
		for(l=0,k=j+1;k<=n;k++) l+=a[i][k]*ans[k];
		for(k=3;k<=9;k++)
			if((a[i][j]*k%7+7)%7==((b[i]-l)%7+7)%7) ans[i]=k;
	}
	for(i = 1;i < n;i ++) printf("%d ",ans[i]);
	cout << ans[i] << endl;
} 
int main(){
	init();
	while (scanf("%d%d",&n,&m) && n && m){
		memset(a,0,sizeof a);
		memset(b,0,sizeof b);
		memset(ans,0,sizeof ans);
		for (int i = 1; i <= m;i++){
			scanf("%d", &num);
			cin >> s >> e;
			b[i] = (data[e] - data[s] + 8) % 7;
			while(num--){
				scanf("%d",&x);
				a[i][x]++;
			}
			for(int j = 1;j <= n;j++)	a[i][j] %= 7;
		}
		solve();
	}
}

我还是不理解。

练习

POJ1487 Single-Player Games

原题链接:Single-Player Games

分析

我咋这么不理解呢?彻底放弃了。

正解

cpp 复制代码
#include <cstring>
#include <algorithm>
#include <cstdio>
#include <cmath>
#include <cstdlib>
using namespace std;
typedef long double LD;
const LD Eps=1e-8;
const int N=30;
int n,Case=0,now,pos[N];
char str[300];
bool free_x[N];
LD a[N][N],x[N];
void GetLn(){
    while (getchar()!='\n');
}
int Match_Pracket(int now){
    int len=strlen(str+1),p=0;
    for (int i=now;i<=len;i++){
        if (str[i]=='(')
            p++;
        if (str[i]==')')
            p--;
        if (!p)
            return i;
    }
    return -1;
}
bool Is_Num_Part(char ch){
    return ch=='-'||('0'<=ch&&ch<='9');
}
int GetNum(int now,int &Next){
    int len=strlen(str+1),f=1,x=0;
    if (str[now]=='-')
        f=-1;
    else
        x=str[now]-'0';
    while (Is_Num_Part(str[++now]))
        x=x*10+str[now]-'0';
    Next=now;
    return x*f;
}
void dfs(int L,int R,LD p){
    if (L>R)
        return;
    int tot=0,i;
    for (i=L;i<=R;){
        if (Is_Num_Part(str[i])){
            int j,v=GetNum(i,j);
            i=j,tot++;
            continue;
        }
        if (str[i]=='('){
            i=Match_Pracket(i)+1;
            tot++;
            continue;
        }
        if ('a'<=str[i]&&str[i]<='z'){
            i++,tot++;
            continue;
        }
        i++;
    }
    p=p/tot;
    for (int i=L;i<=R;){
        if (Is_Num_Part(str[i])){
            int j,v=GetNum(i,j);
            i=j,a[now][n]-=p*v;
            continue;
        }
        if (str[i]=='('){
            int j=Match_Pracket(i);
            dfs(i+1,j-1,p);
            i=j+1;
            continue;
        }
        if ('a'<=str[i]&&str[i]<='z')
            a[now][str[i]-'a']+=p;
        i++;
    }
}
int Gauss(){
    memset(free_x,0,sizeof free_x);
    memset(pos,0,sizeof pos);
    int k,c;
    for (k=c=0;k<n&&c<n;k++,c++){
        int Mk=k;
        for (int i=k+1;i<n;i++)
            if (fabs(a[Mk][c])<fabs(a[i][c]))
                Mk=i;
        if (Mk!=k)
            for (int i=c;i<=n;i++)
                swap(a[Mk][i],a[k][i]);
        if (fabs(a[k][c])<Eps){
            k--;
            free_x[c]=1;
            continue;
        }
        pos[k]=c;
        for (int i=k+1;i<n;i++)
            if (fabs(a[i][c])>Eps){
                for (int j=n;j>=c;j--)
                    a[i][j]=a[i][j]-a[k][j]/a[k][c]*a[i][c];
                a[i][c]=0;
            }
    }
    for (int i=k;i<n;i++)
        if (fabs(a[i][n])>Eps)
            return -1;
    memset(x,0,sizeof x);
    for (int i=k-1;i>=0;i--){
        if (free_x[pos[i]])
            continue;
        LD tmp=a[i][n];
        for (int j=pos[i]+1;j<n;j++){
            if (fabs(a[i][j])<Eps)
                continue;
            if (free_x[j]){
                free_x[pos[i]]=1;
                break;
            }
            tmp-=a[i][j]*x[j];
        }
        if (!free_x[pos[i]])
            x[pos[i]]=tmp/a[i][pos[i]];
        if (fabs(x[pos[i]])<Eps)
            x[pos[i]]=0;
    }
    return 0;
}
int main(){
    while (~scanf("%d",&n)&&n){
        GetLn();
        memset(a,0,sizeof a);
        for (now=0;now<n;now++){
            a[now][now]-=1;
            gets(str+1);
            int pos=1;
            while (str[pos]!='=')
                pos++;
            dfs(pos+1,strlen(str+1),1);
        }
        int ans=Gauss();
        printf("Game %d\n",++Case);
        for (int i=0;i<n;i++)
            if (free_x[i])
                printf("Expected score for %c undefined\n",i+'a');
            else
                printf("Expected score for %c = %.3Lf\n",i+'a',x[i]);
        puts("");
    }
    return 0;
}
相关推荐
DeltaTime2 小时前
三 视图变换, 投影变换, 正交投影, 透视投影
c++·图形渲染
丝斯20112 小时前
AI学习笔记整理(34)——视觉大模型在自动驾驶中的应用
人工智能·笔记·学习
superman超哥2 小时前
仓颉Result类型的错误处理模式深度解析
c语言·开发语言·c++·python·仓颉
八月的雨季 最後的冰吻2 小时前
FFmepg-- 38-ffplay源码-缓冲区 audio_buf调试
c++·ffmpeg·音视频
会思考的猴子2 小时前
UE5 C++ 笔记 GameplayAbilitySystem人物角色
c++·笔记·ue5
wdfk_prog2 小时前
[Linux]学习笔记系列 -- [fs]fs_context
linux·笔记·学习
Binky6782 小时前
力扣--贪心篇(1)
数据结构·算法·leetcode
sinat_255487812 小时前
文件I/O流
java·jvm·算法
深蓝海拓2 小时前
PySide6从0开始学习的笔记(十六) 定时器QTimer
笔记·python·qt·学习·pyqt