BZOJ1211樹的計數

裸的prufer結論。html

給個小連接prufer序列 ,裏面有一個性質4就是本題答案,嚴謹證實能夠上網找一找,若是從多組組合角度理解也能夠。ios

剩下的就是特判,n==1時,du==0,1個,du!=0,廢了。有du==0,廢了。度數和大於(仍是不等於來着?)2*(n-1),廢了。拿到67分……。ide

接着就是求那個式子了,我有一套O(n)拆一個階乘的理論。那這個就是O(n^2)了唄。   spa

#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<vector>
#include<queue>
#include<stack>
#include<set>
#include<map>
#define ll long long 
using namespace std;
ll ans=1,n,du[250],sum,prime[300],prime_num;
bool v[350];
ll read(){
    ll sum=0;int f=1;char x=getchar();
    while(x<'0'||x>'9'){
        if(x=='-') f=-1;
        x=getchar();
    }while(x>='0'&&x<='9'){
        sum=sum*10+x-'0';
        x=getchar();
    }return sum*f;
}
void doprime(int x){
    for(int i=2;i<=x;i++){
        if(!v[i]) prime[++prime_num]=i;
        for(int j=1;j<=prime_num&&i*prime[j]<=x;j++){
            v[i*prime[j]]=1;
            if(i%prime[j]==0) break;
        }
    }
}
ll qpow(ll x,ll k){
    ll ans=1;
    for(;k;k>>=1,x=x*x)
        if(k&1) ans=ans*x;
    return ans;
}
int main(){
    n=read();
    if(n==1){
        du[1]=read();
        if(!du[1]) puts("1");
        else puts("0");
        return 0;
    }
    for(int i=1;i<=n;i++){
        du[i]=read();
        if(!du[i]){
            puts("0");
            return 0;
        }
        sum+=du[i];
    }
    if(sum!=2*(n-1)){
        puts("0");
        return 0;
    }
    doprime(n);
    for(int i=1;i<=prime_num;i++){
        int s=0;
        for(int j=n-2;j/=prime[i];) s+=j;
        for(int j=1;j<=n;j++)
            for(int k=du[j]-1;k/=prime[i];) s-=k;
        ans=ans*qpow(prime[i],s);
    }printf("%lld",ans);
    return 0;
}
View Code
相關文章
相關標籤/搜索