您的位置:首页 > 其它

bzoj1005: [HNOI2008]明明的烦恼

2016-02-11 23:04 309 查看

链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1005

题意:中文题。。。

分析:prufer序列的应用,因为题目已经限制了一些节点的度,那么我们只要在prufer序列里取出x[i]-1个位置给它即可,若prufer序列中还有sum个位置没有被分配节点编号,那么就是那没有度数限制的g个节点任意去即g^sum中方案。那么前面的组合数学*g^sum就是答案啦。

代码:

#include<map>
#include<set>
#include<cmath>
#include<queue>
#include<math.h>
#include<cstdio>
#include<vector>
#include<string>
#include<cstring>
#include<iostream>
#include<algorithm>
#pragma comment(linker, "/STACK:102400000,102400000")
using namespace std;
const int N=1020;
const int MAX=151;
const int MOD1=100000007;
const int MOD2=100000009;
const double EPS=0.00000001;
typedef long long ll;
const ll MOD=9999991;
const ll INF=10000000010;
typedef unsigned long long ull;
int a
,bo
,p
[7],q
[7];
void deal() {
int i,j,w,k=0,n=1010;
memset(bo,0,sizeof(bo));
bo[1]=1;
for (i=2;i<=n;i++) {
if (!bo[i]) a[++k]=i;
for (j=1;j<=k;j++) {
if (a[j]*i>n) break ;
bo[a[j]*i]=1;
if (i%a[j]==0) break ;
}
}
memset(p,0,sizeof(p));
for (i=1;i<=k;i++) {
w=a[i];
while (w<=n) { p[w][0]++;p[w][p[w][0]]=a[i];w+=a[i]; }
}
memset(q,0,sizeof(q));
for (i=1;i<=n;i++) {
w=i;
for (j=1;j<=p[i][0];j++) {
while (w%p[i][j]==0) { q[i][j]++;w/=p[i][j]; }
}
}
}
int x
,ans[N*100],num
;
void add(int x) {
for (int i=1;i<=p[x][0];i++) num[p[x][i]]+=q[x][i];
}
void sub(int x) {
for (int i=1;i<=p[x][0];i++) num[p[x][i]]-=q[x][i];
}
int main()
{
int i,j,k,g,n,flag=0,sum;
scanf("%d", &n);
deal();sum=n-2;g=0;
for (i=1;i<=n;i++) {
scanf("%d", &x[i]);
if ((x[i]<1&&x[i]!=-1)||(x[i]>=n)) flag=1;
if (x[i]!=-1) sum-=x[i]-1;
else g++;
}
if (flag||sum<0||(g==0&&sum>0)) { printf("0\n");return 0; }
memset(ans,0,sizeof(ans));
ans[0]=ans[1]=1;
for (i=1;i<=sum;i++) {
for (j=1;j<=ans[0];j++) ans[j]*=g;
for (j=1;j<ans[0];j++) { ans[j+1]+=ans[j]/10;ans[j]%=10; }
while (ans[ans[0]]>9) { ans[ans[0]+1]=ans[ans[0]]/10;ans[ans[0]]%=10;ans[0]++; }
}
memset(num,0,sizeof(num));
for (i=1;i<=n-2;i++) add(i);
for (i=1;i<=sum;i++) sub(i);
for (i=1;i<=n;i++)
if (x[i]>1) {
for (j=1;j<x[i];j++) sub(j);
}
for (i=1;i<=1000;i++)
if (num[i]) {
for (j=1;j<=num[i];j++) {
for (k=1;k<=ans[0];k++) ans[k]*=i;
for (k=1;k<ans[0];k++) { ans[k+1]+=ans[k]/10;ans[k]%=10; }
while (ans[ans[0]]>9) { ans[ans[0]+1]=ans[ans[0]]/10;ans[ans[0]]%=10;ans[0]++; }
}
}
for (i=ans[0];i>0;i--) printf("%d", ans[i]);printf("\n");
return 0;
}

/*
3
1 -1 -1
4
-1 -1 -1 2
*/
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: