组合数学+高精度 - 看电影(movie)(BZOJ 2227)

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/weixin_42557561/article/details/100034043

传送门


Analysis

真的好棒的一道题啊!!!!
概率即为合法方案除以总方案
总方案显然是 k n k^n

合法方案就很妙了
考虑增加一个位置,连成环
那么所有的方案就都合法了(随便怎么选都可以使得每个人找到位置坐下)有 ( k + 1 ) n (k+1)^n 种,由于是圆排列,所以要除以 ( k + 1 ) (k+1)
然后再考虑破环成链,每一个空位置我们都可以断开,有 k + 1 n (k+1-n) 种方法
(因为如果这个位置是空的,那么一定没有人跨过它,否则就应该在这个位置优先坐下)

所以最终答案就是
a n s = ( k + 1 ) n 1 ( k + 1 n ) k n ans=\frac{(k+1)^{n-1}*(k+1-n)}{k^n}

然后就调高精度去吧~


Code
#include<bits/stdc++.h>
#define in read()
#define re register
using namespace std;
inline int read(){
	char ch;int f=1,res=0;
	while((ch=getchar())<'0'||ch>'9') if(ch=='-') f=-1;
	while(ch>='0'&&ch<='9'){
		res=(res<<1)+(res<<3)+(ch^48);
		ch=getchar();
	}
	return f==1?res:-res;
}
int T,n,k;
int a[205],b[205];
struct BigNumber{
	int len,s[505];//s长度
	BigNumber(){
		memset(s,0,sizeof(s));//!!!!!
		len=0;
	}
	inline void operator = (int x){
		BigNumber res;
		res.len=0;
		while(x){
			res.s[++res.len]=x%10;
			x/=10;
		}
		*this=res;
	}
	inline BigNumber operator *(const BigNumber y){
		BigNumber res;
		res.len=y.len+len;
		for(re int i=1;i<=y.len;++i)
			for(re int j=1;j<=len;++j){
				res.s[i+j-1]+=y.s[i]*s[j];
				res.s[i+j]+=res.s[i+j-1]/10;
				res.s[i+j-1]%=10;
			}
		int &l=res.len;
		while(res.s[l]) res.s[l+1]+=res.s[l]/10,res.s[l]%=10,l++;
		while(!res.s[l]) l--;
		return res;
	}
	void out(){
		for(re int i=len;i>=1;--i) printf("%d",s[i]);
		printf(" ");
	}
	
}a1,b1;
void work(){
	int t=k;
	for(re int i=2;i<=200;++i){
		while(t%i==0){
			t/=i;
			a[i]+=n;
		}
	}
	t=k+1;
	for(re int i=2;i<=200;++i){
		while(t%i==0){
			t/=i;
			b[i]+=n-1;
		}
	}
	t=k+1-n;
	for(re int i=2;i<=200;++i){
		while(t%i==0){
			t/=i;
			b[i]++;
		}
	}
	for(re int i=2;i<=200;++i){
		int hh=min(a[i],b[i]);
		a[i]-=hh;b[i]-=hh;
	}
	a1=1;b1=1;
	for(re int i=2;i<=200;++i){
		BigNumber tmp;
		tmp=i;
		while(a[i]){
			a1=a1*tmp;
			a[i]--;
		}
	}
	for(re int i=2;i<=200;++i){
		BigNumber tmp;
		tmp=i;
		while(b[i]){
			b1=b1*tmp;
			b[i]--;
		}
	}
}
int main(){
	scanf("%d",&T);
	while(T--){
		n=in;k=in;
		if(k<n){
			printf("0 1\n");
			continue;
		} 
		memset(a,0,sizeof(a));
		memset(b,0,sizeof(b));
		work();
		b1.out();
		a1.out();
		printf("\n");
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_42557561/article/details/100034043