1 条题解

  • 0
    @ 2025-11-19 0:10:10

    题解

    (n1)(n-1) 维空间里给出 n+1n+1 个点,它们一定满足一条线性关系,因此凸包只可能是“两个 (n1)(n-1) 维单纯形共用同一个底面”的形状。若把所有点都投影到同一个基准点 PP,那么以其它 nn 个点与 PP 的向量作为行向量组成的 (n1)×(n1)(n-1)\times(n-1) 行列式的绝对值,恰好就是这 nn 个点构成的单纯形的体积乘以 (n1)!(n-1)!

    令其中任意一个点为“被删除的点”。对每个删除的点,把剩下的 nn 个点拿出来,用第一个点作为基准,写出 n1n-1 个向量并计算行列式(用高斯消元即可)。把所有删除点得到的行列式绝对值加起来,就等于两个单纯形体积和的两倍。最后除以 22,并对 109+710^9+7 取模,即为答案。

    #include<algorithm>
    #include<iostream>
    #include<cstring>
    #include<vector>
    #include<cstdio>
    #include<bitset>
    #include<queue>
    #include<ctime>
    #include<cmath>
    #include<set>
    #include<map>
    #define infile(filename) freopen(filename".in","r",stdin)
    #define outfile(filename) freopen(filename".out","w",stdout)
    #define usefile(filename) infile(filename),outfile(filename)
    using namespace std; typedef long long ll; typedef unsigned long long ull; typedef __int128 I;
    namespace IO {
    	const int BUF=1<<20; static char ch[BUF]={},out[BUF]={},*l=ch,*r=ch,*o=out;
    #define FASTIO
    #ifdef FASTIO
    	inline char gc() { return (l==r&&(r=(l=ch)+fread(ch,1,BUF,stdin),l==r))?EOF:*l++; }
    #else
    	inline char gc() { return getchar(); }
    #endif
    	inline void flush() { fwrite(out,1,o-out,stdout),o=out; }
    	inline void putc(char ch) { if(o==out+BUF) flush(); *o++=ch; }
    	struct flusher{~flusher(){flush();}}_;
    }; using IO::gc; using IO::putc;
    template <typename T> void read(T &a) { static char fushu,ch; a=fushu=0; do ch=gc(); while(ch!='-'&&(ch<48||ch>57)); if(ch=='-') ch=gc(),fushu=1; do a=(a<<1)+(a<<3)+(ch^48),ch=gc(); while(ch>47&&ch<58); if(fushu) a=-a; }
    template <typename T,typename ...Args> void read(T &a,Args &...args) { read(a),read(args...); }
    template <typename T> void write(T a) { static char que[114]={},*p=que; if(!a) putc(48); if(a<0) putc('-'),a=-a; while(a) *p++=(a%10)^48,a/=10; while(p!=que) putc(*--p); putc(32); }
    template <typename T,typename ...Args> void write(T a,Args ...args) { write(a),write(args...); }
    template <typename T> void ckmax(T &a,T b) { if(a<b) a=b; }
    template <typename T> void ckmin(T &a,T b) { if(b<a) a=b; }
    const int N=40; const double eps=1e-6;
    int T,n,p[N][N]={}; double a[N][N]={};
    double det(int n) {
    	int i,j,k; double muler,ans=1;
    	for(i=1;i<=n;++i) {
    		for(j=i+1,k=i;j<=n;++j)
    			if(fabs(a[j][i])>fabs(a[k][i]))
    				k=j;
    		swap(a[i],a[k]);
    		if(fabs(a[i][i])<eps) return 0;
    		ans*=a[i][i];
    		for(j=i+1;j<=n;++j)
    			if(fabs(a[j][i])>eps) {
    				muler=a[j][i]/a[i][i];
    				for(k=i;k<=n;++k)
    					a[j][k]-=a[i][k]*muler;
    			}
    	}
    	return ans;
    }
    int main()
    {
    	// usefile("atmo");
    	int i,j,k,tot,fir; double ans=0;
    	read(T);
    	loop : --T;
    	read(n);
    	for(i=1;i<=n+1;++i)
    		for(j=1;j<n;++j)
    			read(p[i][j]);
    	for(i=1,ans=0;i<=n+1;++i) {
    		for(j=1,tot=0;j<=n+1;++j)
    			if(i!=j) {
    				if(!tot) fir=j;
    				for(k=1;k<n;++k)
    					a[tot][k]=p[j][k]-p[fir][k];
    				++tot;
    			}
    		ans+=fabs(round(det(n-1)));
    	}
    	ans/=2.0;
    	printf("%lld\n",ll(round(ans))%1000000007ll);
    	if(T) goto loop;
    	return 0;
    }
    
    • 1

    信息

    ID
    5472
    时间
    1000ms
    内存
    256MiB
    难度
    6
    标签
    递交数
    1
    已通过
    1
    上传者