首先我们来捋一捋整个题的思路吧。

题意要求我们求凸多面体的重心$O$,

之后$O$作为大圆的圆心,作二面角,求每一个凸多边形在球面上的投影面积。

成功解决此题。

那么具体的话。。。

重心的求法也就是

物理的质心求法:

$\overrightarrow{o}=\frac{\sum\limits_{i=1}^n \overrightarrow{a_i}v_i}{V}$

其中$a_i$为四面体重心,$v_i$为这个四面体的体积,$V=\sum_{i=1}^n v_i$。

其中四面体重心坐标为$\overrightarrow{a}=\frac{\overrightarrow{p_1}+\overrightarrow{p_2}+\overrightarrow{p_3}+\overrightarrow{p_4}}{4}$,

$v=\frac{1}{6}|a\cdot(b\times c)|$,这个叫向量混合积,有兴趣可以去搜一下。

质心求法的证明类似于将两个点$p_1,p_2$,与它们的体积$v_1,v_2$

看成两个物体,然后把这两个物体看成一个整体,然后求出这个整体的重心。

实际上就是杠杆定理:设$p_o$为重心,则$v_1(dis_{p_1\rightarrow p_o})=v_2(dis_{p_o\rightarrow p_2})$。

然后就是不断地求重心的过程,最后得到的就是那个式子。

二面角的解法运用法向量求解即可。

即$\text{cos} ~\theta=\frac{\overrightarrow{a}\cdot\overrightarrow{b}}{|\overrightarrow{a}||\overrightarrow{b}|}$,法向量用叉积求。

因为凸多边形投影在球面上也是一个曲面凸多边形。

那么来说,可以把这个图形分成多个三角形进行处理,加起来$/4\pi$即为答案。

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<cstdlib>
#include<vector> 
#define gc getchar()
#define ll long long
#define ull unsigned long long
#define file(s) freopen(s".in","r",stdin);freopen(s".out","w",stdout)
#define I inline 
using namespace std;
const int N=1e4+5,M=1e4;
const double pi=acos(-1);
template<class o>I void qr(o &x)
{
    char c=gc;int f=1;x=0;
    while(c<'0'||c>'9'){if(c=='-')f=-1;c=gc;}
    while(c>='0'&&c<='9'){x=x*10+(c^48);c=gc;}
    x*=f;
}
template<class o>I void qw(o x)
{
    if(x<0)x=-x,putchar('-');
    if(x/10)qw(x/10);
    putchar(x%10+48);
}
struct Point
{
    double x,y,z;
    Point(double x=0.0,double y=0.0,double z=0.0):x(x),y(y),z(z){}
    I Point operator +(const Point &a)const{return Point(x+a.x,y+a.y,z+a.z);}
    I Point operator -(const Point &a)const{return Point(x-a.x,y-a.y,z-a.z);}
    I Point operator *(const double &a)const{return Point(x*a,y*a,z*a);}
    I Point operator /(const double &a)const{return Point(x/a,y/a,z/a);}
    Point operator +=(const Point &a){return *this=*this+a;}
    Point operator -=(const Point &a){return *this=*this-a;}
    Point operator *=(const double &a){return *this=*this*a;}
    Point operator /=(const double &a){return *this=*this/a;}
    I double dis(){return sqrt(x*x+y*y+z*z);}
}P[55],G;int n,m;vector<Point>S[85];
I Point cross(const Point &a,const Point &b){return Point(a.y*b.z-a.z*b.y,a.z*b.x-a.x*b.z,a.x*b.y-a.y*b.x);}
I double dot(const Point &a,const Point &b){return a.x*b.x+a.y*b.y+a.z*b.z;}
I Point getG(const Point &p,const Point &a,const Point &b,const Point &c){return (p+a+b+c)/4.0;} 
double getV(Point p,Point a,Point b,Point c){a-=p;b-=p;c-=p;return fabs(dot(a,cross(b,c)))/6.0;}
double angle(Point p,Point a,Point b,Point c){a-=p;b-=p;c-=p;Point d=cross(a,b),e=cross(a,c);return acos(dot(d,e)/d.dis()/e.dis());}
void init()
{
    qr(n),qr(m);
    for(int i=1;i<=n;i++)
    {
        double x,y,z;scanf("%lf%lf%lf",&x,&y,&z);
        P[i]=Point(x,y,z);
    }
    for(int i=1,k,x;i<=m;i++)
    {
        qr(k);
        for(int j=1;j<=k;j++)qr(x),S[i].push_back(P[x]);
    }
    double sv=0.0;
    for(int i=1;i<=m;i++)
    {
        int s=S[i].size();
        for(int j=0;j<s;j++)
        {
            Point tmp=getG(P[1],S[i][j],S[i][(j+1)%s],S[i][(j+2)%s]);double v=getV(P[1],S[i][j],S[i][(j+1)%s],S[i][(j+2)%s]);
            G+=tmp*v;sv+=v;
        }
    }
    G/=sv;
}
void solve()
{
    for(int i=1;i<=m;i++)
    {
        int s=S[i].size();double ans=-(s-2)*pi;
        for(int j=0;j<s;j++)
            ans+=angle(G,S[i][j],S[i][(j+1)%s],S[i][(j-1+s)%s]);
        ans/=4.0*pi;
        printf("%.7lf\n",ans);
    }
}
int main()
{
    init();
    solve();
    return 0;
}