Luogu P4035 球形空间产生器 题解

Luogu P4035 球形空间产生器 题解

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

思路

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

我们假设球心的坐标为 \((x_1,x_2,\dots,x_n)\) ,给出的点的坐标依次为 \((a_1,a_2,\dots,a_n),(b_1,b_2,\dots,b_n),\dots,(k_1,k_2,\dots,k_n)\)

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

\[(a_1-x_1)^2+(a_2-x_2)^2+\dots+(a_n-x_n)^2\\ =(b_1-x_1)^2+(b_2-x_2)^2+\dots+(b_n-x_n)^2\\ =\dots=(k_1-x_1)^2+\dots+(k_n-x_n)^2 \]

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

\[(a_1-x_1)^2+(a_2-x_2)^2+\dots+(a_n-x_n)^2\\ =(b_1-x_1)^2+(b_2-x_2)^2+\dots+(b_n-x_n)^2 \]

开括号

\[a_1^2-2a_1x_1+x_1^2+a_2^2-2a_2x_2+x_2^2+\dots+a_n^2-2a_nx_n+x_n^2\\ =b_1^2-2b_1x_1+x_1^2+b_2^2-2b_2x_2+x_2^2+\dots+b_n^2-2b_nx_n+x_n^2 \]

观察到等式两边都有\((x_1^2+x_2^2+\dots+x_n^2)\) ,消去,同时将常数项移至等式右边,将未知数移至等式左边

\[(2b_1-2a_1)x_1+(2b_2-2a_2)x_2+\dots+(2b_n-2a_n)x_n\\ =-a_1^2+b_1^2-a_2^2+b_2^2-\dots-a_n^2+b_n^2 \]

可以发现,对于这 \((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 @ 2022-06-17 21:34  Locked_Fog  阅读(66)  评论(0)    收藏  举报