LOJ2047 气氛

气氛

有人向住在北大街的这 \(n\) 个人提了 \(n-1\) 个问题,根据每个人的回答,他会被分配一个 \(n-1\) 维的零一坐标,也就是一个点。这样 \(n\) 个点可以恰好构成一个 \(n-1\) 维空间中的凸包。

北大街的居民认为,在这个多面体内,便是华夏;多面体之外,便是蛮夷。我们可以很容易的计算出华夏部分的广义凸包体积。

有一天,清华路的 B 君来北大街玩,听说了这个故事觉得很有趣,于是也试着给出了这 \(n - 1\) 个问题的答案,

清华路的 B 君,当然认为自己属于华夏,但是北大街表示在 \(n-1\) 维空间中如果有 \(n+1\) 个点的话,华夏部分的体积难以计算。

这下子气氛突然江化。所以这个问题就留给你了,输入 \(n - 1\) 维度空间中的 \(n + 1\) 个点,求广义凸包的体积。

由于这个体积可能不是整数,你只需要输出体积乘以 \(n - 1\) 的阶乘,然后对 \(1000000007\) 取模的结果。

\(1 \leq t \leq 100\)\(3 \leq n \leq 35\),点的坐标一定是 \(0\) 或者 \(1\)

题解

http://jklover.hs-blog.cf/2020/05/30/Loj-2407-气氛-Luft/#more

高维多面体的体积计算 + 高斯消元的一个 trick.

如果只有 \(n\)\(n-1​\) 维的点,那么凸包其实就是它们围成的高维多面体.

它的体积就是选一个起点, 将 \(n-1\)\(n-1\) 维向量形成的矩阵的行列式绝对值除掉 \((n-1)!​\) .

现在有 \(n+1\) 个点,求它们形成的凸包体积.

有一个通用的结论,这 \(n+1\)\(n-1\) 维点的凸包体积等于任选出 \(n\) 个点的高维多面体体积之和 \(/2​\) .

枚举哪一个点没选,用高斯消元求出其余 \(n​\) 个点形成的高维多面体体积即可.

注意不能直接在模意义下计算,否则只能算出行列式在模意义下的值,但无法判定符号,得出绝对值.

所以必须要用真实值消元,为了避免 double 的精度误差,可以将真实值和模意义下的值分别维护.

最后根据真实值的符号决定是否对模意义下的值取相反数.

时间复杂度 \(O(t\cdot n^4)\) .

O int N=40;
int n,p[N][N],b[N][N];
float128 a[N][N];

int solve(){
	int ans=1;
	float128 res=1;
	for(int i=1;i<=n-1;++i){
		int p=i;
		for(int j=i;j<=n-1;++j)if(b[j][i]) {p=j; break;}
		if(!b[p][i]) return 0;
		if(p!=i){
			swap(b[p],b[i]),swap(a[p],a[i]);
			ans=mod-ans,res=-res;
		}
		ans=mul(ans,b[i][i]),res*=a[i][i];
		int inv=fpow(b[i][i],mod-2);
		for(int j=i+1;j<=n-1;++j)if(b[j][i]){
			int coef=mul(mod-b[j][i],inv);
			float128 tmp=-a[j][i]/a[i][i];
			for(int k=i;k<=n-1;++k)
				b[j][k]=add(b[j][k],mul(b[i][k],coef)),a[j][k]+=a[i][k]*tmp;
		}
	}
	if(res<0) ans=mod-ans;
	return ans;
}
void real_main(){
	read(n);
	for(int i=1;i<=n+1;++i)
		for(int j=1;j<=n-1;++j) read(p[i][j]);
	int ans=0;
	for(int ban=1;ban<=n+1;++ban){
		int st=ban==1?2:1;
		int tot=0;
		for(int i=1;i<=n+1;++i)if(i!=ban and i!=st){
			++tot;
			for(int j=1;j<=n-1;++j)
				a[tot][j]=p[i][j]-p[st][j],b[tot][j]=add(p[i][j],mod-p[st][j]);
		}
		ans=add(ans,solve());
	}
	ans=mul(ans,i2);
	printf("%d\n",ans);
}
int main(){
	for(int T=read<int>();T--;) real_main();
	return 0;
}

posted on 2020-06-03 19:04  autoint  阅读(221)  评论(0编辑  收藏  举报

导航