bzoj1211 tree count x bzoj1005 troubles solution to a problem plainly (Prufer sequence)

Count [HNOI2004] Tree: 1211

Time Limit: 10 Sec  Memory Limit: 162 MB
Submit: 3432  Solved: 1295
[Submit][Status][Discuss]

Description

A tree of n nodes, it is assumed that node is v1, v2, respectively, ..., VN, known in the i-th node vi degree of DI, Q satisfying such conditions the number of trees different trees. Given n, d1, d2, ..., dn, satisfies the number of programming required output d (vi) = di tree.

Input

The first line is a positive integer n, the tree has n nodes. The second row has the number n, denotes the i-th degree di, of the i th node, i.e. tree. Where 1 <= n <= 150, to ensure that the input data satisfies the condition of the tree does not exceed 10 ^ 17.

Output

Output to meet the conditions of the tree how many trees.

Sample Input

4
2 1 2 1

Sample Output

2
 
 
 

Properties of the Xiandiu Prufer sequence:

1. correspondence with unrooted trees.

2. The degree is $ d_i $ dot will appear $ d_i-1 $ Prufer times in sequence.

3. The number of spanning a complete graph $ $ n-th node is $ n ^ {n-2} $

  Explain: prufer sequence length $ n-2 $, $ n-$ per Location possibilities.

4. For a given degree of each point unrooted trees, a total of $ \ frac {(n-2 )!} {\ Prod \ limits _ {i = 1} ^ n {(d_i-1)!}} $ Species Happening.

  In fact, one $ d_i-1 $ I $ $ remodelable full array.

 

This question would then cut off just fine with the above conclusion. Numbers by a combination of direct decomposition of the quality factor, remember to Japanese sentence and $ n == 1 $ without Unicom.

#include<cstdio>
#include<iostream>
#include<cstring>
const int N=155;
int d[N],n;
int vis[N],pri[N],res[N],tot,sum,ans[N*5],bu[N];
void getprime()
{
    for(int i=2;i<=n;i++)
    {
        if(!vis[i])pri[++tot]=i,res[i]=tot;
        for(int j=1;j<=tot;j++)
        {
            if(pri[j]*i>n)break;
            vis[i*pri[j]]=1;res[i*pri[j]]=j;
            if(i%pri[j]==0)break;
        }
    }
}
void divi(int x,int val)
{
    while(x!=1)bu[res[x]]+=val,x/=pri[res[x]];
}
void mult(int a[],int x)
{
    int k=0;
    for(int i=1;i<=a[0];i++)
    {
        int tmp=a[i]*x+k;
        a[i]=tmp%10;
        k=tmp/10;
    }
    while(k)a[++a[0]]=k%10,k/=10;
}
int main()
{
    scanf("%d",&n);
    if(n==1)
    {
        int deg;
        scanf("%d",&deg);
        if(!deg)puts("1");
        else puts("0");
        return 0;
    }
    getprime();
    for(int i=1;i<=n;i++)
    {
        scanf("%d",&d[i]);
        if(!d[i])
        {
            puts("0");
            return 0;
        }
        sum+=d[i]-1;
    }
    if(sum!=n-2)
    {
        puts("0");
        return 0;
    }
    for(int i=n-2;i>=2;i--)
        divi(i,1);
    for(int i=1;i<=n;i++)
    {
        for(int j=d[i]-1;j>=2;j--)
            divi(j,-1);
    }
    ans[0]=ans[1]=1;
    for(int i=1;i<=tot;i++)
        while(bu[i]--)mult(ans,pri[i]);
    for(int i=ans[0];i;i--)
        printf("%d",ans[i]);
    return 0;
}
View Code

 

1005: [HNOI2008] obviously troubles

Time Limit: 1 Sec  Memory Limit: 162 MB
Submit: 7125  Solved: 2818
[Submit][Status][Discuss]

Description

  Since obviously learned tree, the tree on the right strange generated interest ...... given numbered 1 to N points, and the final degree certain points, allowing
the connection between any two points may be how many degrees to meet the requirements of the tree was generated?

Input

  The first behavior N (0 <N <= 1000 ),
the next N rows, row i + 1-Di given degree of node i, if the degree is not required, enter -1

Output

  An integer representing the number of the tree meet different requirements, no solution outputs 0

Sample Input

3
1
-1
-1

Sample Output

2

HINT

  Two trees are 1-2-3; 1-3-2

 

The problem is that some point this question is the degree of uncertainty.

Therefore, we first find the $ sum = \ sum d_i-1 $, then selecting from these the overall length of the $ n-2 $

The number of remaining uncertain for some degree, we set of known power point is $ cnt $

So now $ n-2-sum $ positions may be arbitrarily arranged $ n-cnt $ points

Easy to get a final answer

$C_{n-2}^{sum}*\frac{(n-2)!}{\prod \limits _{i=1}^{cnt} {(d_i-1)!}}*(n-cnt)^{n-2-sum}$

 

#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;
typedef long long ll;
const int N=1005;
int d[N],n;
int vis[N],pri[N],res[N],tot,sum,cnt,ans[N*5],bu[N];
void getprime()
{
    for(int i=2;i<=n;i++)
    {
        if(!vis[i])pri[++tot]=i,res[i]=tot;
        for(int j=1;j<=tot;j++)
        {
            if(pri[j]*i>n)break;
            vis[i*pri[j]]=1;res[i*pri[j]]=j;
            if(i%pri[j]==0)break;
        }
    }
}
void divi(int x,int val)
{
    while(x!=1)bu[res[x]]+=val,x/=pri[res[x]];
}
void mult(int a[],int x)
{
    int k=0;
    for(int i=1;i<=a[0];i++)
    {
        int tmp=a[i]*x+k;
        a[i]=tmp%10;
        k=tmp/10;
    }
    while(k)a[++a[0]]=k%10,k/=10;
}

int main()
{
    scanf("%d",&n);
    getprime();
    for(int i=1;i<=n;i++)
    {
        scanf("%d",&d[i]);
        if(d[i]!=-1)sum+=d[i]-1,cnt++;
    }
    for(int i=n-2;i>=2;i--)
        divi(i,1);
    for(int i=n-2-sum;i>=2;i--)
        divi(i,-1);
    for(int i=1;i<=n;i++)
    {
        if(d[i]!=-1)
        {
            for(int j=d[i]-1;j>=2;j--)
                divi(j,-1);
        }
    }
    ans[0]=ans[1]=1;
    for(int i=1;i<=n-2-sum;i++)
        mult(ans,n-cnt);
    for(int i=1;i<=tot;i++)
        while(bu[i])mult(ans,pri[i]),bu[i]--;
    for(int i=ans[0];i>=1;i--)
        printf("%d",ans[i]);
    return 0;
}
View Code

 

Guess you like

Origin www.cnblogs.com/Rorschach-XR/p/11240290.html