zoukankan      html  css  js  c++  java
  • CF451E Devu and Flowers

    题目传送门

    Description

    (n)种花((nleq20)),每种花不超过(f_i)朵,问总数为(s)的方案数

    Solution

    容斥+组合数学

    因为(n)很小,考虑容斥,即无任何限制的方案数(-)至少一种不满足的方案数(+)至少两种不满足的方案数。。。

    如何求无任何限制的方案数?问题可以转化为(x_1+x_2+dots+x_n=s)的非负解数,用组合数学的隔板法解决,方案数为(C^{n-1}_{s+n-1})

    如何求至少一种不满足的方案数?答案为(sum_{i=1}^{n}C_{s-f_i-1+n-1}^{n-1})。因为至少要让一种花的数量在限制外。

    那么解法呼之欲出了。每到一种花递归求解该种强制不选或随意的方案数,强制不选就使(s-=(f_i+1)),随意就将(s)继续递归,同时维护容斥系数即可。

    时间复杂度(O(n2^n))

    细节见代码:

    #include<bits/stdc++.h>
    #define int long long
    #define rep(i, a, b) for (register int i=(a); i<=(b); ++i)
    #define per(i, a, b) for (register int i=(a); i>=(b); --i)
    using namespace std;
    const int N=25, P=1e9+7;
    void add(int &a, int b){a=a+b>=P?a+b-P:a+b;}
    int mul(int a, int b){return a*b-a*b/P*P;}
    int f[N], inv[N], n, s, sum;
    
    inline int read()
    {
        int x=0,f=1;char ch=getchar();
        for (;ch<'0'||ch>'9';ch=getchar()) if (ch=='-') f=-1;
        for (;ch>='0'&&ch<='9';ch=getchar()) x=(x<<1)+(x<<3)+ch-'0';
        return x*f;
    }
    
    int C(int n, int m)
    {
        if (n<m) return 0; int res=1;
        rep(i, 1, m) res=mul(res, mul((n-i+1)%P, inv[i]));
        return res;
    }
    
    int dfs(int i, int s, int sign)
    {
        if (s<0) return 0;
        if (i==n+1) return sign*C(s+n-1, n-1);
        int ans=dfs(i+1, s, sign);
        add(ans, dfs(i+1, s-f[i]-1, 0-sign));
        return ans<0?ans+P:ans;
    }
    
    signed main()
    {
        n=read(); s=read();
        rep(i, 1, n) f[i]=read(), sum+=f[i];
        inv[1]=1; rep(i, 2, n) inv[i]=mul(inv[P%i], P-P/i);
        printf("%d
    ", sum<s?0:dfs(1, s, 1));
        return 0;
    }
    
    
  • 相关阅读:
    手摸手带你用Hexo撸博客(三)之添加评论系统
    手摸手带你用Hexo撸博客(二)之配置主题
    手摸手带你用Hexo撸博客(一)
    vue3和vue2生命周期的对比
    如何根据key合并数组中的对象
    webpack之require.context实现前端工程自动化
    js常用方法封装
    首页
    CentOS7安装MySQL8
    印象笔记代码高亮最完美解决方式
  • 原文地址:https://www.cnblogs.com/ACMSN/p/10652533.html
Copyright © 2011-2022 走看看