UESTC488 组合计数

题意:

       长度为n的非递减序列,现已知其中m个位置上数的位置(一定知道首尾的数字),求还原该序列有多少种方案数,序列各位和的期望是多少?

分析:

      每两个已知位置之间的问题相互独立,

      则需要解决一个MIN>=A[I], MAX<=A[I+1]的非递减序列有多少种方案,序列和的期望是多少?

      方案数:

      因为N个数的非递减排列数只有一种,即这是一个组合问题。

      可对应组合数学中“N种物品中选出K个,有多少种方案数”,C(N+K-1, N-1).

      注:该模型用隔板法理解,将这K个物品通过插入N-1个隔板分成N份,即在最终的N+K-1个位置中选N-1个放上隔板。

        期望:

      所有方案数中每个可选数的出现次数是相同的,即满足A[I]到A[I+1]上的均匀分布,每位上的期望为(A[I]+A[I+1])/2;

      那K个位置的期望为 k*(A[I]+A[I+1])/2;

        组合数计算:

        C(N,K)= N! / ( K! * ( N - K )! ),通过求逆元计算。

     当P为素数时,a的逆元 = [ a ^ (p-2) ] % p


具体实现:    

     RE了一发,因为没有考虑组合数最大是N+K+1为底的,开成了10^6

#include <cstdio>
#include <algorithm>
#include <queue>
#include <cstring>
#include <cmath>
#include <set>
#include <vector>
#define mod 1000000009
using namespace std;
typedef long long LL;

LL a[2000],b[2000];
LL jc[2000100];

void init()
{
    jc[0]=1;
    for(int i=1;i<=2000010;i++)
        jc[i]=jc[i-1]*i%mod;
}

LL quick_pow(LL n,LL m)
{
    LL ans=1;
    while(m>0)
    {
        if(m&1)
            ans=(ans*n)%mod;
        n=(n*n)%mod;
        m>>=1;
    }
    return ans;
}

LL get_rev(LL n)
{
    return quick_pow(n,mod-2);
}

LL cal(LL n,LL m)
{
    return jc[n]*get_rev(jc[m])%mod*get_rev(jc[n-m])%mod;
}
int main()
{
    LL n,m;
    int T;
    init();
    scanf("%d",&T);
    for(int t=1;t<=T;t++)
    {
        scanf("%lld %lld",&n,&m);
        for(int i=0;i<m;i++)
            scanf("%lld",&a[i]);
        for(int i=0;i<m;i++)
            scanf("%lld",&b[i]);
        LL ca=1;
        double sum=0;
        for(int i=0;i<m-1;i++)
        {
            sum+=b[i];
            LL num=b[i+1]-b[i]+1;
            LL k=a[i+1]-a[i]-1;
            if(k==0) continue;
            ca=(ca*cal(num+k-1,min(k,n-1)))%mod;
            sum+=(double)k*(b[i]+b[i+1])/2;
        }
        sum+=b[m-1];
        printf("Case #%d: %lld %.3lf\n",t,ca,sum);
    }
    return 0;
}


  

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值