您的位置:首页 > Web前端

prufer序列

2016-05-05 11:34 267 查看
给一棵树,它的prufer序列由一下步骤得到:

(1)选择度数为1的编号最小的点,把它删掉并把和它相连的点加入序列

(2)重复第一步直到剩下两个点

prufer序列的性质:

长度为n-2,记每个点的度数为di,那么每个点都会在prufer序列中出现di-1次

那么prufer序列有什么用呢?很显然(但不知道为什么→_→,但直觉上能感觉到)每棵不同的树都对应一个不同的prufer序列,那么当我们遇到一些需要计算不同的树的个数时就可以把问题转化成组合数学计算啦

bzoj1005代码:

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<string>
#include<iomanip>
#include<vector>
#include<set>
#include<map>
#include<queue>

using namespace std;
typedef long long LL;
typedef unsigned long long ULL;

#define rep(i,k,n) for(int i=(k);i<=(n);i++)
#define rep0(i,n) for(int i=0;i<(n);i++)
#define red(i,k,n) for(int i=(k);i>=(n);i--)
#define sqr(x) ((x)*(x))
#define clr(x,y) memset((x),(y),sizeof(x))
#define pb push_back
#define mod 1000000007
int n,m,pcnt,p[2000],a[1010],b[1010],d[1010];
bool vis[1010];
const int maxn=3010;

struct bign
{
int len,s[maxn];
bign()
{
memset(s,0,sizeof(s));
len=1;
}
bign(int num){*this=num;}
bign(const char *num){*this=num;}
bign operator = (const int num)
{
if(num==0)
{
len=1;
memset(s,0,sizeof(s));
return *this;
}
char s[maxn];
sprintf(s,"%d",num);
*this=s;
return *this;
}
bign operator = (const char *num)
{
for(int i=0;num[i]=='0';num++);
len=strlen(num);
for(int i=0;i<len;i++)s[i]=num[len-i-1]-'0';
return *this;
}
void clean()
{
while(len>1&&!s[len-1])len--;
}
bign operator *(const bign &b)
{
bign c;
c.len=len+b.len;
for(int i=0;i<len;i++)
{
for(int j=0;j<b.len;j++)
{
c.s[i+j]+=s[i]*b.s[j];
}
}
for(int i=0;i<c.len;i++)
{
c.s[i+1]+=c.s[i]/10;
c.s[i]%=10;
}
c.clean();
return c;
}
string str() const
{
string res="";
for(int i=0;i<len;i++)res=char(s[i]+'0')+res;
return res;
}
};

ostream& operator << (ostream &out,const bign &x)
{
out<<x.str();
return out;
}

bign quipow(bign x,int k)
{
bign ret=1;
while(k)
{
if(k&1)ret=ret*x;
x=x*x;
k>>=1;
}
return ret;
}

int main()
{
pcnt=0;
for(int i=2;i<=1000;i++)
{
if(!vis[i])p[++pcnt]=i;
for(int j=1;j<=pcnt && i*p[j]<=1000;j++)
{
vis[i*p[j]]=1;
a[i*p[j]]=p[j];
if(i%p[j]==0)break;
}
}

scanf("%d",&n);
m=0;
rep(i,1,n)
{
scanf("%d",&d[m+1]);
if(d[m+1]!=-1)m++;
}
if(n<=2)
{
if(n==1)puts(d[1]>0?"0":"1");
else if(n==2)
{
bool flag=0;
rep(i,1,m)if(d[m]!=1)flag=1;
puts(flag?"0":"1");
}
return 0;
}
d[m+1]=n-2;
rep(i,1,m)d[m+1]-=d[i]-1;
if(d[m+1]<0)
{
puts("0");
return 0;
}
rep(i,2,n-2)b[i]++;
rep(i,1,m)rep(j,2,d[i]-1)b[j]--;
rep(i,2,d[m+1])b[i]--;
bign ans=1;
red(i,n-2,2)
{
if(!vis[i])ans=ans*quipow(i,b[i]);
else
{
b[i/a[i]]+=b[i];
b[a[i]]+=b[i];
}
}
ans=ans*quipow(n-m,d[m+1]);
cout<<ans<<endl;

return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: