Codeforces1153F Serval and Bonus Problem 【组合数】

题目分析:

我们思考正好被k个区间覆盖的情况,那么当前这个子段是不是把所有的点分成了两个部分,那么在两个部分之间相互连k条线,再对于剩下的分别连线就很好了?这个东西不难用组合数写出来。

然后我们要证明每个区间的期望长度是点数加一分之一,这个很容易,归纳法证明就行了。

 

代码:

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 
 4 const int mod = 998244353;
 5 
 6 int n,k,l;
 7 int f[10200];
 8 int fac[10200],inv[10200],pw[10200];
 9 
10 int C(int nn,int kk){
11     return 1ll*fac[nn]*inv[kk]%mod*inv[nn-kk]%mod;
12 }
13 int A(int nn,int kk){
14     return 1ll*fac[nn]*inv[nn-kk]%mod;
15 }
16 
17 int fast_pow(int now,int pw){
18     int ans = 1,dt = now,bit = 1;
19     while(bit <= pw){
20     if(bit & pw){ans = 1ll*ans*dt%mod;}
21     dt = 1ll*dt*dt%mod; bit<<=1;
22     }
23     return ans;
24 }
25 
26 int work(int rm){
27     int ll = 0,r = 2*n;int Rp = fast_pow(f[2*n],mod-2);
28     int ans = 0;
29     while(r>=0){
30     int now = C(ll,rm),im = A(r,rm);
31     int res = 1ll*now*im%mod*f[ll-rm]%mod*f[r-rm]%mod*pw[rm]%mod;
32     res = 1ll*res*Rp%mod;
33     ans += res; ans%=mod;
34     ll++; r--;
35     }
36     ans = 1ll*ans*fast_pow(2*n+1,mod-2)%mod*l%mod;
37     return ans;
38 }
39 
40 int main(){
41     scanf("%d%d%d",&n,&k,&l);
42     f[0] = 1;fac[0] = 1;pw[0] = 1;
43     for(int i=1;i<=2*n;i++) pw[i] = 2*pw[i-1]%mod,fac[i] = 1ll*fac[i-1]*i%mod;
44     for(int i=2;i<=2*n;i++){
45     f[i] = 2ll*f[i-2]%mod*(i-1)%mod;
46     }
47     inv[2*n] = fast_pow(fac[2*n],mod-2);
48     for(int i=2*n-1;i>=0;i--) inv[i] = 1ll*inv[i+1]*(i+1)%mod;
49     int ans = 0;
50     for(int i=k;i<=n;i++) ans += work(i),ans%=mod;
51     printf("%d\n",ans);
52     return 0;
53 }

 

posted @ 2019-04-27 12:07  menhera  阅读(211)  评论(0编辑  收藏  举报