zoukankan      html  css  js  c++  java
  • Luogu2624 HNOI2008小明的烦恼

    一道好题:

    Description

    link

    (n) 个点在无根树树上的度数,如果 (d_i=-1) 那就是随便

    求树的计数

    (nle 1000)

    Solution

    前置知识:(purfer) 序列,高精度乘法

    什么?不会? (Luogu) 模板区欢迎您

    这个题用 (purfer) 序列转成序列上的计数

    然后就计数呗

    一个序列 (n-2) 个位置,钦定 (m) 个元素的个数

    求合法序列的个数

    先设 (sum=sumlimits_{i=1}^m d_i-1)

    然后上多重集排列

    [inom{n-2}{sum}frac {sum!} {prod_{i=1}^m (d_i-1)!} ]

    剩下还有 (n-2-sum) 个位置

    每个位置还有 (n-m) 中选择

    所以答案直接就有了对吧

    [inom{n-2}{sum}frac {sum!} {prod_{i=1}^m d_i!} imes (n-m)^{n-2-sum} ]

    我们还发现这个题要写高精

    用从前向后找质因子,然后就只用写高精乘法就好了

    Code

    #include<bits/stdc++.h>
    using namespace std;
    #define int long long
    namespace yspm{
    	inline int read()
    	{
    		int res=0,f=1; char k;
    		while(!isdigit(k=getchar())) if(k=='-') f=-1;
    		while(isdigit(k)) res=res*10+k-'0',k=getchar();
    		return res*f;
    	}
    	struct node{
    		int len,a[100100];
    		inline void init(int x)
    		{
    			memset(a,0,sizeof(a)); len=0;
    			while(x) a[++len]=x%10,x/=10;
    			return ;
    		}
    		inline void clear(){memset(a,0,sizeof(a)); return ;}
    		inline void print()
    		{
    			for(int i=len;i>=1;--i) putchar(a[i]+'0'); 
    			return puts(""),void();
    		}
    	};
    	inline node mul(node p,int q)
    	{
    		for(int i=1;i<=p.len;++i) p.a[i]*=q; 
    		for(int i=1;i<=p.len;++i) p.a[i+1]+=p.a[i]/10,p.a[i]%=10; 
    		while(p.a[p.len+1]) p.len++,p.a[p.len+1]+=p.a[p.len]/10,p.a[p.len]%=10; 
    		return p;
    	}
    	const int N=10100;
    	int d[N],sum,cnt;
    	int f[N],fl[N],pri[N],md[N],num,n;
    	inline void prework()
    	{
    		for(int i=2;i<N;++i)
    		{
    			if(!fl[i]) fl[i]=i,pri[++num]=i;
    			for(int j=1;j<=num&&i*pri[j]<N;++j)
    			{
    				if(pri[j]>fl[i]) break;
    				fl[i*pri[j]]=pri[j];
    			}
    		} return ;
    	}
    	signed main()
    	{
    		prework(); n=read(); 
    		for(int i=1;i<=n;++i)
    		{
    			d[i]=read(); 
    			if(d[i]==0) return puts("0"),0;
    			if(d[i]>0) cnt++,sum+=d[i]-1;  
    		}
    		if(sum>n-2) return printf("%lld
    ",0),0;
    		for(int i=1;i<=n-2;++i) ++f[i];
    		for(int i=1;i<=sum;++i) --f[i];
    		for(int i=1;i<=n-2-sum;++i) --f[i];
    		f[n-cnt]+=n-2-sum;
    		for(int i=1;i<=sum;++i) ++f[i];
    		for(int i=1;i<=n;++i) 
    		{
    			if(d[i]>=0) 
    			{
    				for(int j=1;j<=d[i]-1;++j) f[j]--;	
    			}
    		}
    		for(int i=2020;i>=2;--i) 
    		{
    			if(fl[i]==i) continue;
    			f[fl[i]]+=f[i]; f[i/fl[i]]+=f[i]; f[i]=0;
    		} 
    		node ans; ans.init(1); 
    		for(int i=1;i<=num;++i)
    		{
    			if(!f[pri[i]]) continue;
    			while(f[pri[i]]>0) f[pri[i]]--,ans=mul(ans,pri[i]);
    		} ans.print();
    		return 0;
    	}
    }
    signed main(){return yspm::main();}
    

    Review

    如果出题人丧心病狂地把数据开到 (10^5) 呢?

    (FFT+) 线段树就好了对吧

  • 相关阅读:
    2020年秋招三星面试题
    物联网金融和互联网金融的区别与联系
    数据库事务的4种隔离级别
    Access-cookie之sqlmap注入
    SDL-软件安全开发周期流程
    图片马的制作
    ssrf内网端口爆破扫描
    逻辑漏洞_验证码绕过_密码找回漏洞
    平行越权与垂直越权
    xff注入
  • 原文地址:https://www.cnblogs.com/yspm/p/12823421.html
Copyright © 2011-2022 走看看