您的位置:首页 > 其它

BZOJ1005: [HNOI2008]明明的烦恼

2017-01-20 20:37 411 查看

Description

  自从明明学了树的结构,就对奇怪的树产生了兴趣......给出标号为1到N的点,以及某些点最终的度数,允许在

任意两点间连线,可产生多少棵度数满足要求的树?

Input

  第一行为N(0 < N < = 1000),

接下来N行,第i+1行给出第i个节点的度数Di,如果对度数不要求,则输入-1

Output

  一个整数,表示不同的满足要求的树的个数,无解输出0

Sample Input

3

1

-1

-1

Sample Output

2

HINT

  两棵树分别为1-2-3;1-3-2

Source

树的prufer编码 http://hzwer.com/3272.html
题解说的很清楚,不再赘述
#include <bits/stdc++.h>

using namespace std;

const int MAXN = 1010;
const int mod = 1000000;

int n, d[MAXN], tot, ans[MAXN], len, m, prime[MAXN], cnt, chk[MAXN], num[MAXN];

inline void init()
{
for( int i = 2 ; i <= 1000 ; i++ )
{
if( !chk[ i ] ) prime[ ++cnt ] = i;
for( int j = 1 ; prime[ j ] * i <= 1000 ; j++ )
{
chk[ i * prime[ j ] ] = 1;
if( i % prime[ j ] == 0 ) break;
}
}
}

inline void solve(int q, int flag)
{
for( int i = 1 ; i <= q ; i++ )
{
int x = i;
for( int j = 1 ; j <= cnt ; j++ ) while( x % prime[ j ] == 0 ) num[ j ] += flag, x /= prime[ j ];
}
}

inline void mul(int x)
{
for( int i = 1 ; i <= len ; i++ ) ans[ i ] *= x;
for( int i = 1 ; i <= len ; i++ ) ans[ i + 1 ] += ans[ i ] / mod, ans[ i ] %= mod;
while( ans[ len + 1 ] ) len++, ans[ len + 1 ] += ans[ len ] / mod, ans[ len ] %= mod;
}

inline void print()
{
for( int i = len ; i ; i-- )
{
if( i == len ) printf( "%d", ans[ i ] );
else printf( "%06d", ans[ i ] );
}
}

int main()
{
init(); ans[ len = 1 ] = 1;
scanf( "%d", &n );
if( n == 1 )
{
scanf( "%d", &d[ 1 ] );
if( !d[ 1 ] || d[ 1 ] == -1 ) return printf( "1\n" ), 0;
return printf( "0\n" ), 0;
}
for( int i = 1 ; i <= n ; i++ )
{
scanf( "%d", &d[ i ] );
if( !d[ i ] ) return printf( "0\n" ), 0;
if( d[ i ] == -1 ) m++;
else { tot += --d[ i ]; }
}
if( tot > n - 2 ) return printf( "0\n" ), 0;
solve( n - 2, 1 );
solve( n - 2 - tot, -1 );
for( int i = 1 ; i <= n ; i++ ) solve( d[ i ], -1 );
for( int i = 1 ; i <= cnt ; i++ )
while( num[ i ]-- ) mul( prime[ i ] );
for( int i = 1 ; i <= n - 2 - tot ; i++ ) mul( m );
return print(), 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: