E. 乐乐吃糖

在这里插入图片描述
很明显, 这是一道组合题
乍一看,是隔板,好像又不是
在这里插入图片描述
隔板怎么可以是小于等于呢——当然可以

例子:
x 1 + x 2 + x 3 ≤ n x_1+x_2+x_3\le n x1+x2+x3n
我们可以发现
n − x 1 − x 2 − x 3 ≥ 0 n-x_1-x_2-x_3\ge 0 nx1x2x30
所以一定存在一个正整数 x 4 x_4 x4使得 x 1 + x 2 + x 3 + x 4 = n x_1+x_2+x_3+x_4=n x1+x2+x3+x4=n
小于等于问题解决了
然后是 0 ≤ x i ≤ c i 0\le x_i\le c_i 0xici
其实就是容斥原理,不过因为 x i x_i xi可以为零,所以减去 c i c_i ci的同时还要多减去一
最麻烦的在于它的模数2004
不是质数,时限又是100ms
所以,我们要在算组合数的时候速战速决,又不能用逆元
于是,一种全新的方法出现了——在取模的同时又要保证是分母的倍数,于是可以预处理出分母,计算时取 2004 × 2004\times 2004×分母的模
题目结束了

#include <bits/stdc++.h>
using namespace std;
#define int long long
const int N = 2007, md = 1e9 + 7;
int n, c[N], a, b;
int C(int a, int b)
{
    if (a < b)
        return 0;
    int ans = 1, c = 1;
    for (int i = 1, j = a; i <= b; i++, j--)
        c *= i;
    for (int i = 1, j = a; i <= b; i++, j--)
        ans = ans * j % (2004 * c);
    return ans / c;
}
int solve(int a, int b, int x)
{
    // cout << x << endl;
    if (a > n)
        return b * C(x + n, n) % 2004;
    return (solve(a + 1, b, x) + solve(a + 1, -b, x - c[a] - 1)) % 2004;
}
signed main()
{
    scanf("%lld%lld%lld", &n, &a, &b);
    for (int i = 1; i <= n; i++)
        scanf("%lld", c + i);
    printf("%lld", ((solve(1, 1, b) - solve(1, 1, a - 1)) % 2004 + 2004) % 2004);
}
// 2026*3=6078
  • 18
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值