Luogu P4035 球形空间产生器 题解

Luogu P4035 球形空间产生器 题解

题目传送门:P4035省选/NOI-

思路

这道题的难点在于如何将这个连等式转化为方程

我们假设球心的坐标为 (x1,x2,,xn) ,给出的点的坐标依次为 (a1,a2,,an),(b1,b2,,bn),,(k1,k2,,kn)

根据题目提示,很容易想到以下等式:

(a1x1)2+(a2x2)2++(anxn)2=(b1x1)2+(b2x2)2++(bnxn)2==(k1x1)2++(knxn)2

我们拆分出其中的两个多项式:

(a1x1)2+(a2x2)2++(anxn)2=(b1x1)2+(b2x2)2++(bnxn)2

开括号

a122a1x1+x12+a222a2x2+x22++an22anxn+xn2=b122b1x1+x12+b222b2x2+x22++bn22bnxn+xn2

观察到等式两边都有(x12+x22++xn2) ,消去,同时将常数项移至等式右边,将未知数移至等式左边

(2b12a1)x1+(2b22a2)x2++(2bn2an)xn=a12+b12a22+b22an2+bn2

可以发现,对于这 (n+1) 个连等的多项式,我们可以每次取出其中的相邻的两个多项式,然后仿照上面的方法化简,最终得到 n 个等式构成的 n 元一次方程组

而解这个方程组则可以使用高斯消元法

代码
#include<bits/stdc++.h>
using namespace std;
#define GO(u,v,i) for(register int i=u;i<=v;i++)
template<class t>inline t fr(){
    register t num=0,dis=1;
    register char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')dis=-1;ch=getchar();}
    while(ch<='9'&&ch>='0'){num=(num<<1)+(num<<3)+(ch^48);ch=getchar();}
    return num*dis;
}
template<class t>inline void fw(t num){
    if(num>9)fw(num/10);
    putchar(num%10+'0');
}
template<class t>inline void fw(t num,char ch){
    if(num<0)num=-num,putchar('-');
    fw(num);putchar(ch);
}
typedef double lf;
const int maxn=10+12;
const lf eps=1e-6;
int n;
lf a[maxn][maxn];

inline void gauss(lf a[][maxn],int n){
    int maxi;
    GO(1,n,i){
        maxi=i;
        GO(i+1,n,j)if(fabs(a[j][i])>fabs(a[maxi][i]))maxi=j;
        if(maxi^i)GO(1,n+1,j)swap(a[i][j],a[maxi][j]);
        lf tmp=a[i][i];
        GO(i,n+1,j)a[i][j]/=tmp;
        GO(i+1,n,j){
            if(fabs(a[j][i])>eps){
                tmp=a[j][i];
                GO(i,n+1,k)a[j][k]-=tmp*a[i][k];
            }
        }
    }
}

inline void prnt(lf a[][maxn],int n){
    for(int i=n;i>0;i--){
        GO(1,i-1,j)a[j][n+1]-=a[i][n+1]*a[j][i];
        if(fabs(a[i][n+1])<eps)a[i][n+1]=0;
    }
    
    GO(1,n,i)printf("%.3lf ",a[i][n+1]);
}

signed main(){
    n=fr<int>();
    GO(1,n+1,i)GO(1,n,j)scanf("%lf",&a[i][j]);
    GO(1,n,i){
        GO(1,n,j){//常数项
            a[i][n+1]-=a[i][j]*a[i][j];
        	a[i][n+1]+=a[i+1][j]*a[i+1][j];
        }
        GO(1,n,j){//各项系数
            a[i][j]=-2*a[i][j];
        	a[i][j]+=2*a[i+1][j];
        }
    }
    gauss(a,n);//高斯消元
    prnt(a,n);//求解输出
    return 0;
}
posted @   Locked_Fog  阅读(43)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示
主题色彩