Hackerrank Connect the country

題目鏈接:
https://www.hackerrank.com/challenges/connect-the-country

由於n的整數拆分不超過6000 我們可以考慮用每個整數拆分表示一個狀態
預處理每個狀態之間的轉移 然後暴力跑

複雜度不是很會證明 反正跑得過去

#include<cstdio>
#include<map>
#include<cmath>
#include<cstring>
#include<vector>
#include<cstdlib>
using namespace std;

char c;
inline void read(int&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 cnt;

struct RE
{
    int con[31];
    inline int &operator[](int x){return con[x];}
    inline friend bool operator < (RE a,RE b)
    {
        for(int i=0;i<=a[0];i++)    
        if(a[i]^b[i])
        return a[i]<b[i];
        return false;
    }

}A[6001];

int cac[31];

int n;
map<RE,int>M;
map<int,int>R;
void Solve(int x,int y,int z)
{
    if(!x)
    {   
        A[++cnt][0]=n;
        for(int i=1;i<=z;i++)
        A[cnt][cac[i]]++;
        M[A[cnt]]=cnt;
        return;
    }
    for(int i=y;i<=x;i++)
        cac[z+1]=i,Solve(x-i,i,z+1);

}

pair<int,int> Trans[6000][600];
int s[6000];
double P[2][6001];

const
    double eps=1e-8;

int main()
{
    double D=sqrt(2.0),T=sqrt(3.0);
    double A76=sin(D)-sin(T);
//  printf("%.10f\n%.10f\n",1.0,4*sqrt(5));
    read(n);
//n=4;
    Solve(n,1,0);
    for(int i=1;i<=cnt;i++)
    {
        R.clear();
        RE P=A[i];      
        int Sum=n*(n-1)>>1;
        for(int j=1;j<A[i][0];j++)
            if(A[i][j])
            {   
                for(int k=j+1;k<=A[i][0];k++)
                    if(A[i][k])
                    {
                        P[j]--,P[k]--,P[j+k]++;
                        int no=M[P];
                        P[j]++,P[k]++,P[j+k]--;
                        int pp=j*k*P[j]*P[k];
                        R[no]+=pp;
                        Sum-=pp;            
                    }
                    if(P[j]>1)
                    {
                        int k=j;
                        P[j]--,P[k]--,P[j+k]++;
                        int no=M[P];
                        P[j]++,P[k]++,P[j+k]--;
                        int pp=j*k*P[j]*(P[k]-1)>>1;
                        R[no]+=pp;
                        Sum-=pp;            

                    }
            }
        //R[i]=Sum;
        for(map<int,int>::iterator A=R.begin();A!=R.end();A++)
            Trans[i][++s[i]]=make_pair(A->first,A->second);
    }
    int Sum=n*(n-1)>>1;
    int last=1,now=0;
    double ans=0;
    int S;
    P[last][1]=1;
    for(int i=1;i<=Sum;i++,last^=1,now^=1)
    {
        double F=1./(Sum-i+1);
        S=Sum-i+1;
        memset(P[now],0,sizeof(P[now]));
        for(int j=1;j<cnt;j++)
            {
                if(P[last][j]>eps)
                {
                    for(int k=1;k<=s[j];k++)
                    {
                        P[now][Trans[j][k].first]+=P[last][j]*Trans[j][k].second*F;
                        S-=Trans[j][k].second;
                    }
                    P[now][j]+=S*F*P[last][j];
                    S=Sum-i+1;
                }
            }
        ans+=P[now][cnt]*i;
    }
    printf("%d\n",(int)(ans+eps));
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章