zoukankan      html  css  js  c++  java
  • SSLZYC 方案数

    题目大意:
    老师今天买了好多黑色和白色巧克力(可以认为数量无限)来奖励同学们,让同学们自己来拿巧克力,但有如下限制:
    1、每个人最少拿一块巧克力;
    2、每个人只能拿一种颜色的巧克力;
    3、拿黑色巧克力的人不少于C 个;
    4、第i 个人最多拿a[i]个黑巧克力,或最多拿b[i]个白巧克力。
    请问N(编号1~N)个同学拿巧克力可能的方案数是多少?(取模10007即可)
    100%的数据:1≤N≤100000,1≤C≤20,1≤a[i],b[i]≤10^9。


    思路:
    明显是一道完全背包的问题。(巧克力数量是无限的)
    但是这道题的数据很坑,如果我们直接打完全背包,时间复杂度则是O(n^2),很明显会超时。
    那么我们可以换一种思路:
    先求出拿巧克力的总方法,再用完全背包求出小于c人取黑巧克力的方案数(时间复杂度O(nc)),最后用总方法减去小于c人取黑巧克力的方案数,就是我们要求的答案。
    状态转移方程:(f[i][j]=f[i-1][j-1]*a[i]+f[i-1][j]*b[i])


    代码:

    #include <cstdio>
    #include <iostream>
    using namespace std;
    
    int f[100001][21],a[100001],b[100001],sum,ans;
    int n,m;
    
    int main()
    {
        freopen("fas.in","r",stdin);
        freopen("fas.out","w",stdout);
        scanf("%d%d",&n,&m);
        sum=1;
        for (int i=1;i<=n;i++) scanf("%d",&a[i]);
        for (int i=1;i<=n;i++)
        {
            scanf("%d",&b[i]);
            sum=sum*(a[i]+b[i])%10007;  //计算总方案数
        }
        f[0][0]=1;
        for (int i=1;i<=n;i++) f[i][0]=(f[i-1][0]*(b[i]%10007))%10007;  //初始化
        for (int i=1;i<=n;i++)
         for (int j=1;j<=m;j++)  //完全背包
            f[i][j]=((f[i-1][j-1]*(a[i]%10007))%10007+(f[i-1][j]*(b[i]%10007))%10007)%10007;  //当i个人中j个人取了黑巧克力时的方案数
         for (int i=0;i<m;i++)
         {
            sum=(sum-f[n][i])%10007;  //计算总方案数
            if(sum<0) sum+=10007;
         }
        printf("%d\n",sum);
        return 0;
    }
  • 相关阅读:
    mysql--创建表,插入数据,修改表名,删除表,简单查询/内连接、左/右连接
    页面访问过程及get/post的理解——
    对docker一些认知
    selenium之css selector定位
    selenium之xpath定位
    Linux常用命令:修改文件权限chmod 754/744
    对redis的一些理解
    用户登录 用例设计
    mysql优化
    mysql复制问题
  • 原文地址:https://www.cnblogs.com/hello-tomorrow/p/9313118.html
Copyright © 2011-2022 走看看