【枚举】【高斯消元】Gym - 101412D - Find the Outlier

时间:2023-03-08 21:13:47

给你一个未知的d次多项式在0,1,...,d+2处的取值,其中有且只有一个是错的,问你哪个是错的。

枚举哪个是错的,再在剩下的d+2个中取d+1个高斯消元,解出多项式系数,然后代一下最后剩下的那个数看看是否合法,如果合法再看看那个错的是否真的错了。

#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cstring>
using namespace std;
#define N 11
double v[N];
int n;
double B[N][N+1],A[N][N+1],x[N],b[N];
double sqr(double x){return x*x;}
void guass_jordan()
{
memcpy(B,A,sizeof(A));
for(int i=1;i<=n;++i)
B[i][n+1]=b[i];
for(int i=1;i<=n;++i)//枚举:正在消除第i个未知数,之后第i个方程废掉,矩阵行、列-1
{
int pivot=i;
for(int j=i+1;j<=n;++j)//枚举j:把正在处理的未知数的系数的绝对值最大的方程换到第i行
if(fabs(B[j][i])>fabs(B[pivot][i]))
pivot=j;
swap(B[i],B[pivot]);
//if(fabs(B[i][i])<EPS)
//若所有(最大)的该未知数系数为0,说明少一个未知数,有无穷多解
for(int j=i+1;j<=n+1;++j)
B[i][j]/=B[i][i];
for(int j=1;j<=n;++j)
if(i!=j)//枚举所有的方程,从第j个方程中消去第i个未知数
for(int k=i+1;k<=n+1;++k)//依次把第j个方程中的第k个未知数减去应减的数值
B[j][k]-=B[j][i]*B[i][k];
}
for(int i=1;i<=n;++i) x[i]=B[i][n+1];
}
int d;
int main(){
while(1){
scanf("%d",&d);
if(!d){
return 0;
}
memset(B,0,sizeof(B));
memset(A,0,sizeof(A));
memset(x,0,sizeof(x));
memset(b,0,sizeof(b));
n=d+1;
for(int i=0;i<=d+2;++i){
scanf("%lf",&v[i]);
}
for(int i=0;i<=d+2;++i){
for(int j=0;j<=d+2;++j){
if(j!=i){
for(int k=0,l=0;k<=d+2;++k){
if(k!=i && k!=j){
int kk=1;
++l;
for(int p=1;p<=d+1;++p){
A[l][p]=(double)kk;
kk=kk*k;
}
b[l]=v[k];
}
}
guass_jordan();
int jj=1;
double tmp=0;
for(int k=1;k<=d+1;++k){
tmp+=(double)jj*x[k];
jj*=j;
}
if(fabs(tmp-v[j])<0.00001){
int ii=1;
double tmp2=0;
for(int k=1;k<=d+1;++k){
tmp2+=(double)ii*x[k];
ii*=i;
}
if(fabs(tmp2-v[i])>0.01){
printf("%d\n",i);
goto OUT;
}
}
}
}
}
OUT:;
}
return 0;
}