您的位置:首页 > 其它

【BZOJ】【1005】【HNOI2008】明明的烦恼

2015-05-15 21:38 344 查看

Prufer序列/排列组合+高精度

  窝不会告诉你我是先做了BZOJ1211然后才来做这题的>_>(为什么?因为我以前不会高精度呀……)

  在A了BZOJ 1211和1089之后,蒟蒻终于有信心来写这道神题啦= =

  

  嗯还是先说下做法吧~

  ……

  还是出门左转去看黄学长的博客吧……我懒得写了……其实就是Prufer序列+高精度= =嗯就是之前说的那两道题的加和……

  http://hzwer.com/3272.html

/**************************************************************
Problem: 1005
User: Tunix
Language: C++
Result: Accepted
Time:188 ms
Memory:1304 kb
****************************************************************/

//BZOJ 1005
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#define rep(i,n) for(int i=0;i<n;++i)
#define F(i,j,n) for(int i=j;i<=n;++i)
#define D(i,j,n) for(int i=j;i>=n;--i)
#define pb push_back
using namespace std;
typedef long long LL;
inline int getint(){
int r=1,v=0; char ch=getchar();
for(;!isdigit(ch);ch=getchar()) if (ch=='-') r=-1;
for(; isdigit(ch);ch=getchar()) v=v*10-'0'+ch;
return r*v;
}
const int N=1010;
/*******************template********************/

struct bint{
int l,v[5010];
bint(){l=1; memset(v,0,sizeof v);}
int& operator [] (int x){return v[x];}
}ans;
const int Limit=1000;

void print(bint a){
printf("%d",a[a.l]);
D(i,a.l-1,1) printf("%03d",a[i]);
puts("");
}
bint operator * (bint a,int p){
int tmp=0;
F(i,1,a.l){
a[i]=a[i]*p+tmp;
tmp=a[i]/Limit;
a[i]%=Limit;
}
if (tmp) a[++a.l]=tmp;
return a;
}
int n,a
,b
,prime
,tot,m,cnt;
bool vis
;
void ready(int n){
F(i,2,n){
if (!vis[i]) prime[++tot]=i;
F(j,1,tot){
if (i*prime[j]>n) break;
vis[i*prime[j]]=1;
if (i%prime[j]==0) break;
}
}
}
void add(int k,int v){
F(j,1,tot){
int x=k;
while (x){
b[j]+=x/prime[j]*v;
x/=prime[j];
}
}
}
int main(){
#ifndef ONLINE_JUDGE
freopen("1005.in","r",stdin);
freopen("1005.out","w",stdout);
#endif
ready(1000);
n=getint();
if (n==1){
a[1]=getint();
if (a[1]<=0) puts("1");
else puts("0");
return 0;
}
F(i,1,n){
a[i]=getint();
if (a[i]==0 || a[i]>n-1) {puts("0"); return 0;}
}
F(i,1,n){
if (a[i]>0){
a[i]-=1;
m+=a[i];
}
else cnt++;
}
if (m>n-2){ puts("0"); return 0;}
int tmp=n-2;
F(i,1,n){
if (a[i]>0){
add(tmp,1);
add(a[i],-1);
add(tmp-a[i],-1);
tmp-=a[i];
}
}
//  F(i,1,tot) printf("%d ",b[i]); puts("");
ans[1]=1;
F(i,1,tot) F(j,1,b[i]) ans=ans*prime[i];
F(j,1,tmp) ans=ans*cnt;
print(ans);
return 0;
}


View Code

1005: [HNOI2008]明明的烦恼

Time Limit: 1 Sec Memory Limit: 162 MB
Submit: 2964 Solved: 1182
[Submit][Status][Discuss]

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

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