BZOJ3925: [Zjoi2015]地震后的幻想乡

SB题目卡我精度

对于每一个联通块建立一个函数 F(S)=1-Sigma(F(S’))*((1-X)^Side(S,S`))
其中x是边出现的期望值

然后就可以搞到最终集合进行积分

#include<cstdio>
#include<iostream>
#include <iomanip>
#include<cstring>
using namespace std;
#define ll long long
#define lld __float128
struct Poly
{
    ll n;
    ll v[101];
    Poly(){memset(v,0,sizeof(v));}
}Grah[1031];

inline Poly operator *(Poly a,Poly b)
{
    ll i,j;
    Poly c;
    c.n=a.n+b.n-1;
    for(i=0;i<a.n;i++) 
     for(j=0;j<b.n;j++) 
      c.v[i+j]+=a.v[i]*b.v[j]; 
    while(!c.v[c.n-1])c.n--;
   return c;
}

inline Poly operator +(Poly a,Poly b)
{
    ll i,j;
    Poly c;
    c.n=max(a.n,b.n);
    for(i=0;i<c.n;i++) 
      c.v[i]+=a.v[i]+b.v[i]; 
    while(!c.v[c.n-1])c.n--;
   return c;
}

inline Poly operator -(Poly a,Poly b)
{
    ll i,j;
    Poly c;
    c.n=max(a.n,b.n);
    for(i=0;i<c.n;i++) 
      c.v[i]+=a.v[i]-b.v[i]; 
    while(!c.v[c.n-1])c.n--;
   return c;
}

ll Cnt[1024][1024];

Poly base;
Poly D(ll x)
{
    Poly res;
    res.n=1,res.v[0]=1;
    if(x==0)
     return res;
    while(x--)
      res=res*base;
    return res;
}

lld Fir(Poly t,ll x)
{
    lld res=0;
    ll xn=1;
    for(ll i=0;i<t.n;i++)
     {
        res+=xn*t.v[i]/(i+1.00000000000);
        xn*=x;
     }
    return res;
}

char c;
inline void read(ll &a)
{
    a=0;do c=getchar();while(c<'0'||c>'9');
    while(c<='9'&&c>='0')a=(a<<3)+(a<<1)+c-'0',c=getchar();
}
int main()
{
   base.n=2;
   base.v[0]=1,base.v[1]=-1;    
    ll n,m;
    scanf("%lld%lld",&n,&m);
    ll Maxn=1<<n;
    Maxn--;
    ll i,j,k,X,Y,l,t;
    for(i=1;i<=m;i++)
       {
         read(j),read(k);
         t=1<<(j-1);l=1<<(k-1);
          for(X=1;X<=Maxn;X++)
            if((X&t)&&!(X&l))
              for(Y=1;Y<=Maxn;Y++)
               if((Y&l)&&!(Y&t))
               Cnt[X][Y]++,Cnt[Y][X]++;
       }
    for(i=1;i<=n;i++)
     Grah[1<<(i-1)].n=1,Grah[1<<(i-1)].v[0]=1;
    Poly B,T;
    for(i=1;i<=Maxn;i++)
    if(i&1)
    {
        B.n=1,B.v[0]=1;
        T.n=0;memset(T.v,0,sizeof(T.v));
        for(j=1;j<i;j+=2)
        if((i&j)==j)
           {
               T=T+Grah[j]*D(Cnt[j^i][j]);  
           }
        Grah[i]=B-T;
    }
    __float128 MAPLE;
    for(k=(1<<n)-1,i=0;i<Grah[k].n;i++)
        MAPLE+=(__float128)Grah[k].v[i]/(i+(__float128)1);
    lld b=Fir(Grah[Maxn],1);
    cout<<fixed<<setprecision(6)<<(long double)(1-MAPLE)<<endl;
// cout<<fixed<<setprecision(6)<<(long double)(1-b)<<endl;

    return 0;
}

你可能感兴趣的:(BZOJ3925: [Zjoi2015]地震后的幻想乡)