組合數學+高精度 - 看電影(movie)(BZOJ 2227)

傳送門


Analysis

真的好棒的一道題啊!!!!
概率即爲合法方案除以總方案
總方案顯然是knk^n

合法方案就很妙了
考慮增加一個位置,連成環
那麼所有的方案就都合法了(隨便怎麼選都可以使得每個人找到位置坐下)有(k+1)n(k+1)^n種,由於是圓排列,所以要除以(k+1)(k+1)
然後再考慮破環成鏈,每一個空位置我們都可以斷開,有k+1n(k+1-n)種方法
(因爲如果這個位置是空的,那麼一定沒有人跨過它,否則就應該在這個位置優先坐下)

所以最終答案就是
ans=(k+1)n1(k+1n)knans=\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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章