acm-(组合数、方案统计)Sichuan State Programming Contest 2011 H.Rebuild the Sequence

acm-(组合数、方案统计)Sichuan State Programming Contest 2011 H.Rebuild the Sequence
acm-(组合数、方案统计)Sichuan State Programming Contest 2011 H.Rebuild the Sequence
传送门
首先对于第一问,其实等价于对 k k k个物品各自分配一个数字: c 1 , c 2 , c 3 , . . . , c k c_1,c_2,c_3,...,c_k c1​,c2​,c3​,...,ck​,满足 A ≤ c 1 ≤ c 2 ≤ c 3 ≤ . . . ≤ B A\le c_1\le c_2\le c_3\le...\le B A≤c1​≤c2​≤c3​≤...≤B,然后问方案数。

不妨设 c 0 = A , c k + 1 = B c_0=A,c_{k+1}=B c0​=A,ck+1​=B,那么可以求出关于 c c c的差分数组为 d i = c i − c i − 1 d_i=c_i-c_{i-1} di​=ci​−ci−1​,也就是 d 1 , d 2 , . . . , d k + 1 d_1,d_2,...,d_{k+1} d1​,d2​,...,dk+1​,由于 c c c数组单调不减,故满足 d ≥ 0 d\ge 0 d≥0,并且有 d 1 + d 2 + . . . + d k + 1 = B − A d_1+d_2+...+d_{k+1}=B-A d1​+d2​+...+dk+1​=B−A,这个问题相当于在问你为 d d d分配一个非负值满足此表达式,这就是一个非常典型的组合学问题了,利用隔板法容易发现答案为 C B − A + k k C_{B-A+k}^k CB−A+kk​。

然后再看第二问,求整个序列的和的期望,还是像上一问一样考虑子问题,也就是对于 k k k个物品分配的数字 c 1 , c 2 , . . . , c k c_1,c_2,...,c_k c1​,c2​,...,ck​在满足 A ≤ c 1 ≤ . . . ≤ c k ≤ B A\le c_1\le ...\le c_{k}\le B A≤c1​≤...≤ck​≤B的情况下的平均值,如果 k = 1 k=1 k=1的话容易发现答案为 A + B 2 \frac {A+B}2 2A+B​,然后再根据对称性可以发现当 k k k变大后这个平均值不可能不是 A + B 2 \frac{A+B}2 2A+B​,如果平均值偏小的话就会不符合数学中的对称性,因此 E ( c ) = A + B 2 E(c)=\frac{A+B}2 E(c)=2A+B​,那么后面的就好做了。

#include <bits/stdc++.h>
using namespace std;

typedef double db;
typedef long long ll;
const int maxn = 2e6+5;
const int mod = 1e9+9;

int a[maxn],b[maxn],fac[maxn],fav[maxn];
int C(int a,int b){
    if(a<b)return 0;
    return 1ll*fac[a]*fav[a-b]%mod*fav[b]%mod;
}
int qpow(int a,int b,int c){
    int ans=1;
    while(b){
        if(b&1)ans=1ll*ans*a%c;
        b>>=1;
        a=1ll*a*a%c;
    }
    return ans;
}
int main(){
    int t;
    fac[0]=1;
    for(int i=1;i<maxn;++i)fac[i]=1ll*fac[i-1]*i%mod;
    fav[maxn-1]=qpow(fac[maxn-1],mod-2,mod);
    for(int i=maxn-2;i>=0;--i)fav[i]=1ll*fav[i+1]*(i+1)%mod;
    scanf("%d",&t);
    int kase=0;
    while(t--){
        int n,m;
        scanf("%d%d",&n,&m);
        int ans1=1;
        ll ans2=0;
        for(int i=1;i<=m;++i)scanf("%d",&a[i]);
        for(int i=1;i<=m;++i){
            scanf("%d",&b[i]);
        }
        for(int i=1;i<m;++i){
            int k=a[i+1]-a[i]-1;
            ans1=1ll*ans1*C(b[i+1]-b[i]+k,k)%mod;
            ans2+=1ll*(b[i]+b[i+1])*k;
            ans2+=2ll*b[i];
        }
        ans2+=2ll*b[m];
        printf("Case #%d: %d %.3lf\n",++kase,ans1,ans2/2.0);
    }
}

上一篇:HENAU冬令营第一专题H - 字典序


下一篇:问题 E: 对称矩阵的判定