bzoj4403: 序列统计

题意

给定三个正整数N、L和R,统计长度在1到N之间,元素大小都在L到R之间的单调不降序列的数量。输出答案对10^6+3取模的结果。


自己xjbyy的解法

设m=r-l+1.
那么我们先枚举一个i表示这个单调不降序列有多少个不同的数, 那么 Cin 就是选出i个不同的数的方案数,然后我们看剩下的n-i个数,很明显他们可以不选,或者成为这i个数中的一个,此时就对应球盒模型“n-i个相同的球放入i个盒子,盒子可以为空的方案数”,因为球可以不放,我们就新增一个盒子不放的球单独放到这个盒子里,哪么就是“n-i个相同的球放入i+1个盒子,盒子可以为空的方案数”了,这个就等于 Cim 于是最后的答案就是
ni=1CinCim ,然后我们可以考虑化简他:
原式= ni=1CinCmim 我们考察一下这个式子的意义,就是有两个盒子,一个盒子有n个球,一个盒子有m个球,然后一个盒子选i个球 1<=i<=n ,两个盒子一共选m个球的方案数,所以我们完全可以把两个盒子的球混在一起然后选出m个球,那就是 Cmn+m 了,我们发现,这样算的话,i=0这种情况也被算进去了,所以我们应该再减去一个1,哪么最后的答案就是 Cmn+m1 了。
r


突然清醒

突然发现自己是zz:我们这个问题就直接相当于把”n个球放入m个盒子,盒子可以为空,球可以不选”,再减去n个球一个都不选的情况,那就直接是 Cmn+m -1了.

#include<cstdio>
#include<algorithm>

const int P = 1e6 + 3;
typedef long long ll;
int T, n, m;
ll jx[P], jx_rev[P];

int C (int n, int m) {
    if (m > n) return 0;
    return jx[n] * jx_rev[m] % P * jx_rev[n - m] % P;
}

ll Lucas (int n, int m) {
    if (m > n) return 0ll;
    if (n < P) return C (n, m);
    int k = C (n % P, m % P);
    if (k) return Lucas (n / P, m / P) * k % P;
    return 0ll;
}

ll quick_power (ll a, ll b) {
    ll ret = 1;
    for (; b; a = a * a % P, b >>= 1) if (b & 1) ret = ret * a % P;
    return ret;
}

int main () {
    scanf ("%d", &T);
    int l, r;
    jx[0] = 1; for (int i = 1; i < P; ++i) jx[i] = jx[i - 1] * i % P;
    jx_rev[P - 1] = quick_power (jx[P - 1], P - 2);
    for (int i = P - 2; ~i; --i) jx_rev[i] = jx_rev[i + 1] * (i + 1) % P;
    while (T--) {
        scanf ("%d%d%d", &n, &l, &r), m = r - l + 1;
        printf ("%lld\n", (Lucas (n + m, m) - 1 + P) % P);
    }
    return 0;
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值