【题目链接】:
【题意】
让你把f个food和w个wine装在若干个栈里面; 每个栈只能装food或者是wine; 且装wine和food的栈交替出现; 然后是随机等可能地分配方案; 问你wine的栈里面,wine的数量都大于h的概率是多少;【题解】
可以把一个栈里面的东西看成是线性的; 即如果某个栈里面有3个food; 就相当于3个food排成了一排; 这样,原问题等价于; 有f个food放在直线上; 然后有f+1个位置可以放wine; 这f+1个位置中,每个位置放置的wine的数量都必须多于h个; 则先从这f+1个位置中选出i个位置 C(f+1,i) 然后先把这i个位置都放h个wine; 则剩余rest=w-h*i个wine; 然后相当于解一个方程 x1+x2+…+xi=rest且x1,x2..xi都是正整数; 求它的不同解个数; 高中数学题。隔板法; 答案就为 C(rest−1,i−1) 枚举i的时候答案递增 C(f+1,i)∗C(w−h∗i−1,i−1) 这样就能把分子算出来了; 而分母是 C(f+w,w) 即随便选w个位置放wine,其他地方放food就是了; 写个乘法逆元; 然后注意边界,即w=0的时候,这时候是没有wine的了; 所以不存在说wine会小于等于h的情况,即任何方案都可行; 有个f+w,所以阶乘得算到2*1e5…. 【Number Of WA】 4 【完整代码】#includeusing namespace std;#define lson l,m,rt<<1#define rson m+1,r,rt<<1|1#define LL long long#define rep1(i,a,b) for (int i = a;i <= b;i++)#define rep2(i,a,b) for (int i = a;i >= b;i--)#define mp make_pair#define pb push_back#define fi first#define se second#define ms(x,y) memset(x,y,sizeof x)#define Open() freopen("F:\\rush.txt","r",stdin)#define Close() ios::sync_with_stdio(0),cin.tie(0)typedef pair pii;typedef pair pll;const int dx[9] = { 0,1,-1,0,0,-1,-1,1,1};const int dy[9] = { 0,0,0,-1,1,-1,1,-1,1};const double pi = acos(-1.0);const int N = 2e5+100;const LL MOD = 1e9+7;LL fac[N+100],rfac[N+100];LL f,w,h;LL ksm(LL x,LL y){ LL t = 1; while (y) { if (y&1) t = (t*x)%MOD; x = (x*x)%MOD; y>>=1; } return t;}void pre(){ fac[0] = 1; rep1(i,1,N) fac[i] = (fac[i-1]*i)%MOD; rfac[N] = ksm(fac[N],MOD-2); rep2(i,N,1) rfac[i-1] = (rfac[i]*i)%MOD;}LL C(LL n,LL m){ //n!/(n-m!)*m! return (fac[n]*rfac[n-m]%MOD)*rfac[m]%MOD;}int main(){ //Open(); Close();//scanf,puts,printf not use //init?????? pre(); cin >> f >> w >> h; LL fz = 0; for (LL i = 1;i <= f+1;i++) { if ((h+1)*i>w) break; fz = fz+C(f+1,i)*C(w-h*i-1,i-1)%MOD; fz%=MOD; } LL fm = C(f+w,w); if (w==0) fz = fm; LL ans = fz*ksm(fm,MOD-2)%MOD; cout << ans << endl; return 0;}