2227: [Zjoi2011]看電影(movie)

經典思路:線轉化爲圈,利用對稱性
假設有k+1個椅子圍成一圈,每張票上寫着1~k+1(而不是1~k),因爲概率均等,我們統計有多少種方案導致椅子k+1上坐着人
一共有(k+1)n種可能的情況。爲了方便敘述,我們假定每種情況模擬一遍,每次在沒人坐的椅子上放一枚硬幣(每次恰好有k+1-n把椅子沒人坐),則所有情況都模擬完之後每把椅子上都有(k+1-n)(k+1)n-1枚硬幣,也就是說,有(k+1-n)(k+1)n-1種情況下,椅子k+1上沒人坐。
改回每張票寫1~k之後,這個結論不變。——————-from liurujia

#include<bits/stdc++.h>
#define rep(i,k,n) for(int i=k;i<=n;i++)
#define rep2(i,k,n) for(int i=k;i>=n;i--)
using namespace std;
const int N=1000005;
int gcd(int a,int b){return !b ? a : gcd(b,a%b);}
struct gao{
    int num[N],len;
    void init(){len=1;memset(num,0,sizeof(num));}
    void put(){
        printf("%d",num[len]);
        rep2(i,len-1,1)printf("%04d",num[i]);
    }
    void operator*=(int x){
        rep(i,1,len)num[i]*=x;
        for(int i=1;i<=len || num[i];i++)num[i+1]+=num[i]/10000,num[i]%=10000,len=max(len,i);
    }
}A,B;
int T,k,n,a[N],b[N];
int main(){
    scanf("%d",&T);
    while(T--){
        scanf("%d%d",&n,&k);
        if(n>k){printf("0 1\n");continue;}
        rep(i,1,n)a[i]=k+1,b[i]=k;
        a[n]=(k+1-n);
        rep(i,1,n){int d=gcd(a[n],b[i]);a[n]/=d,b[i]/=d;}
        A.init(),B.init();
        A.num[1]=1,B.num[1]=1;
        rep(i,1,n){
            A*=a[i];
            B*=b[i];
        }
        A.put();printf(" ");B.put();puts("");
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章