1 条题解

  • 0
    @ 2025-10-8 16:56:25

    题目:求方程 (x1+x2++xnm)(x_1 + x_2 + \cdots + x_n \leq m) 的非负整数解的个数,其中 (0xiai)(0 \leq x_i \leq a_i )

    解题思路

    1. 组合数基础:方程 (x1+x2++xn=m)(x_1 + x_2 + \cdots + x_n = m) 的非负整数解个数为 (m+n1n1)\binom{m+n-1}{n-1}
    2. 容斥原理:对于有上界限制 xiaix_i \leq a_i 的情况,使用容斥原理排除不满足条件的解。通过枚举所有非空子集,计算每个子集对应的“超界”情况,调整总解数。

    代码实现

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long LL;
    const LL mod=1e9+7;
    LL a[21];
    LL pow_mod(LL a,LL b)
    {
        LL res=1%mod;a%=mod;
        for(;b;b>>=1)
        {
            if(b&1)res=res*a%mod;
            a=a*a%mod;
        }
        return res;
    }
    LL C(LL n,LL m)
    {
        if(n<m)return 0;
        LL s1=1,s2=1;
        for(LL i=n-m+1;i<=n;i++)s1=i%mod*s1%mod;
        for(LL i=1;i<=m;i++)s2=i%mod*s2%mod;
        return s1*pow_mod(s2,mod-2)%mod;
    }
    int main()
    {
        LL n,m;scanf("%lld%lld",&n,&m);
        for(int i=0;i<n;i++)scanf("%lld",&a[i]);
        LL ans=C(m+n-1,n-1);
        for(int i=1;i<(1<<n);i++)
        {
            LL s=0,sign=1;
            for(int j=0;j<n;j++)
            {
                if(i&(1<<j))s=s+(a[j]+1),sign*=-1;
            }
            ans=(ans+C(m+n-1-s,n-1)*sign)%mod;
        }
        printf("%lld",(ans+mod)%mod);
        return 0;
    }
    
    • 1

    *【容斥原理】[CF451E] Devu and Flowers

    信息

    ID
    415
    时间
    1000ms
    内存
    64MiB
    难度
    4
    标签
    递交数
    27
    已通过
    15
    上传者