刚学高斯消元 1e-18 秒,老萌新求助
查看原帖
刚学高斯消元 1e-18 秒,老萌新求助
76039
Wu_Ren楼主2020/12/1 21:40
#include <bits/stdc++.h>
using namespace std;
int m,n,a[510][110],s[110][110],K[110],P[110],T[510],E[110],id[510],rk[510];
long double b[110];
const long double eps=1e-12;
struct mat{
	long double a[110][110];
	void work(){
		for(int i=1,j;i<=n;i++){
			j=i;
			while(j<=n&&a[j][i]<eps&&a[j][i]>-eps) j++;
			if(j>n) continue;
			for(int k=1;k<=n+1;k++) swap(a[i][k],a[j][k]);
			long double t=1.0/a[i][i];
			for(int k=1;k<=n+1;k++) a[i][k]*=t;
			for(int k=1;k<=n;k++){
				if(k==i) continue;
				long long t=a[k][i];
				for(int l=1;l<=n+1;l++) a[k][l]=a[k][l]-a[i][l]*t;
			}
		}
		for(int i=1;i<=n;i++){
			bool falg=false;
			for(int j=1;j<=n;j++){
				if(a[i][j]>eps||a[i][j]<-eps){
					falg=true;
					break;
				}
			}
			if(!falg&&(a[i][n+1]>eps||a[i][n+1]<-eps)) puts("fail"),exit(0);
		}
	}
}d;
int cmp(int x,int y){
	for(int i=1;i<=n+1;i++) b[i]=0;
	int sumx=0,sumy=0;
	for(int j=1;j<=n;j++){
		if(~a[x][j]) sumx+=a[x][j],b[j]+=T[y];
		if(~a[y][j]) sumy+=a[y][j],b[j]-=T[x];
	}
	b[n+1]=sumy*T[x]-sumx*T[y];
	for(int i=1;i<=n;i++){
		if(b[i]<eps&&b[i]>-eps) continue;
		if(d.a[i][i]<eps&&d.a[i][i]>-eps) puts("fail"),exit(0);
		long double t=b[i];
		for(int k=1;k<=n+1;k++) b[k]=b[k]-d.a[i][k]*t;
	}
	return b[n+1]>0;
}
int main(){
	scanf("%d%d",&m,&n);
	for(int i=1;i<=m;i++) for(int j=1;j<=n;j++){
		scanf("%d",&a[i][j]);
		if(~a[i][j]) T[i]++;
	}
	for(int i=1;i<=n;i++) for(int j=1;j<=n;j++){
		for(int k=1;k<=m;k++) if(~a[k][i]&&~a[k][j]) s[i][j]++;
		K[i]+=s[i][j];
	}
	for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) if(~a[j][i]) P[i]+=a[j][i];
	for(int i=1;i<=n;i++) for(int k=1;k<=m;k++) if(~a[k][i]) for(int j=1;j<=n;j++) if(~a[k][j]) E[i]+=a[k][j];
	for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) d.a[i][j]=s[i][j];
	for(int i=1;i<=n;i++) d.a[i][n+1]=(long double)(K[i])*P[i]/s[i][i]-E[i],d.a[i][i]-=K[i];
	d.work();
	for(int i=1;i<=m;i++) id[i]=i;
	stable_sort(id+1,id+m+1,cmp);
	for(int i=m;i>=1;i--) printf("%d\n",id[i]);
}

我的大致思路:

假设第 ii 个学科的偏移值为 did_i

是对 did_i 建立连立方程先高斯消元一遍。

然后对比 X,YX,Y 两个人时,就相当于求 (GX,i+di)×[GX,i1]TX(GY,i+di)×[GY,i1]TY\frac{\sum (G_{X,i}+d_i)\times[G_{X,i}\ne-1]}{T_X}-\frac{\sum (G_{Y,i}+d_i)\times[G_{Y,i}\ne-1]}{T_Y} 是否 <0<0。其中 TiT_i 为第 ii 名学生选了多少学科。然后移项后,变成大概为 di×bi<C\sum d_i\times b_i<C 的形式,拿刚刚解的方程组消掉 did_i,如果消不掉则输出 fail,最后判断式子是否成立。

然后写了一发只 AC#2 #3,其他都是 WA。球球各位大佬帮帮忙/kel/kel。

请不要无脑 %\% 或无意义回复,个人很讨厌这种行为

2020/12/1 21:40
加载中...