• zrt中文题


    orzzrt....

    题意:给n个点n条边,问能形成几个无向连通图
    公式:ans=Σ(k=3~n){[n^(n-k)]* (n-1)!/2(n-k)!}
    推导:ans=Σ(k=3~n)(f(n,k)*h(k))
    f(n,k)表示能形成的森林个数,h(k)表示能形成的环的个数
    h(k)=n!/2n n!:排列的种类 n!/n:去重(123,231,312) (n!/n)/2:去重(123,321)
    ∴h(k)=(k-1)!/2
    设g(n,k)=f(n,k)*(n-k)! (边有编号时森林的个数)
    =n(n-1)n(n-2)*...*n*k
    =n^(n-k)*(n-1)!/(k-1)!
    ∴f(n,k)=n^(n-k)*(n-1)!/[(k-1)!*(n-k)!]
    ∴ans=Σ(k=3~n){[n^(n-k)]* (n-1)!/2(n-k)!}
    需要用到高精度

    #include<iostream>
    #include<algorithm>
    #include<cstring>
    #include<cstdio>
    #include<string>
    #define MAX 10010
    using namespace std;
    char ans[MAX],sum[MAX];
    
    int bigchenfa(int *sum2,int *a,int *b,int lsum,int la,int lb) 
    {
        int i,j,k ; 
        memset(sum2,0,sizeof(sum2)); 
        lsum=0; 
        for(i=1;i<=la;i++) 
        for(j=1,lsum=i-1;j<=lb;j++) 
        sum2[++lsum]+=b[j]*a[i]; 
        for(i=1;i<=lsum;i++)
        if(sum2[i]>=10) 
        {
            if(sum2[lsum]>=10) 
            lsum++; 
            sum2[i+1]+=sum2[i] / 10 ; 
            sum2[i]%=10 ; 
        }
        return lsum ; 
    }
    
    void multiply(int ac)
    {
        int a[MAX]={0},b[MAX]={0},sum2[MAX*2]={0} ; 
          int la=0,lb=1,lsum=0; 
          int i,j;
          int b1=ac;
          la=strlen(ans);  
          for(int i=1,j=la-1;i<=la;i++,j--) a[i]=ans[j]-'0'; 
          while(b1>0)
          {
            b[lb]=b1%10;
            lb++;
            b1/=10;    
        }
        lb-=1;
          lsum = bigchenfa(sum2,a,b,lsum,la,lb) ; 
          memset(ans,0,sizeof(ans));
          for(i=lsum,j=0;i>=1;i--,j++) ans[j]=sum2[i]+'0'; 
    }
    
    int sum1[MAX],ans1[MAX];
    void add()
    {
        int lena,lenb,len;
        lena=strlen(sum);
        lenb=strlen(ans);
        len=max(lena,lenb);
        memset(sum1,0,sizeof(sum1));
        memset(ans1,0,sizeof(ans1));
        for(int i=lena-1,j=0;i>=0;i--,j++)sum1[j]=sum[i]-'0';
        for(int i=lenb-1,j=0;i>=0;i--,j++)ans1[j]=ans[i]-'0';
        for(int i=0;i<len;i++)
        {
            if(sum1[i]+ans1[i]>=10) sum1[i+1]++;
            sum1[i]=(sum1[i]+ans1[i])%10;
        }
        if(sum1[len]!=0)len++;
        memset(sum,0,sizeof(sum));
        for(int i=len-1,j=0;i>=0;i--,j++)
        {
            sum[j]=sum1[i]+'0';
        }
    }
    void divide()
    {
        int a[MAX]={0},c[MAX]={0};
        int i,k,d=0; 
        k=strlen(sum); 
        for(i=0;i<k;i++)
            a[i]=sum[k-i-1] - '0';
        for(i=k-1;i>=0;i--) 
        {
            d=d*10+a[i]; 
            c[i]=d/2;
            d=d%2; 
        }
        while(c[k-1]==0&&k>1) k--; 
        for(i=k-1;i>=0;i--) cout<<c[i];
    }
    
    int main()
    {
        int n;
        cin>>n;
        for(int k=3;k<=n;k++)
        {
            memset(ans,0,sizeof(ans));
            ans[0]='1';
            for(int i=1;i<=n-k;i++)
            {
                multiply(n);    
            }
            for(int i=n-k+1;i<=n-1;i++)
            {
                multiply(i);    
            }
            add();
        }
        divide();
        return 0;
    } 
  • 相关阅读:
    Effective C++第三遍
    SQL基础教程
    hibernate 数据关联多对多
    hibernate 数据关联一对一
    hibernate 数据关联一对多
    hibernate Criteria查询
    hibernate HQL查询
    hibernate 持久化对象的生命周期
    hibernate的配置
    微博登录
  • 原文地址:https://www.cnblogs.com/xiaoxubi/p/6233609.html
Copyright © 2020-2023  润新知