zoukankan      html  css  js  c++  java
  • lightoj 1125【01背包变性】

    题意:

    从n个数里选出m个来,还要使得这m个数之和被d整除。

    给一个n和q,再给n个数,再给q个询问,每个询问包含两个数,d,m;
    对于每个case输出每个q个询问的可行的方案数。

    思路:

    每个数只能被取一次
    那我直接dp一下,dp[i][j]直接代表前i个物品有j值;
    然后j这个值由2^31*200…这就不行了。。。
    虽然可以/d
    变变变!!!
    但是我们可以把余数开一维啊,然后还是前i个物品开一维,但是还有选几个再开一维,那就开三维了。。。
    01背包开两维反着更新一下就好了。
    dp[i][j]代表选i个有j余数的方案数。
    然后考虑C(200,10)DP要开long long
    初始化,不选的时候,dp[0][0]=1;ok。

    code………………

    #include<bits/stdc++.h>
    //#include<cstdio>
    //#include<math.h>
    //#include<string.h>
    //#include<algorithm>
    using namespace std;
    typedef long long LL;
    typedef unsigned long long ULL;
    const double eps=1e-5;
    const double pi=acos(-1.0);
    const int mod=1e8+7;
    const LL INF=0x3f3f3f3f;
    
    const int N=1e2+10;
    
    int a[N*2];
    LL dp[12][25];
    
    int main()
    {
        int cas=1;
        int n,w,q,d,m;
        int t,x,sum;
        scanf("%d",&t);
        while(t--)
        {
            scanf("%d%d",&n,&q);
                for(int i=1;i<=n;i++)
                    scanf("%d",&a[i]);
    
            printf("Case %d:
    ",cas++);
    
            for(int k=1;k<=q;k++)
            {
                scanf("%d%d",&d,&m);
                memset(dp,0,sizeof(dp));
                dp[0][0]=1LL;
                for(int i=1;i<=n;i++)
                {
                    int temp=a[i]%d;
                    for(int j=m;j>=1;j--)
                        for(int x=0;x<d;x++)
                            dp[j][x]+=dp[j-1][(x+2*d-temp)%d];
                }
                printf("%lld
    ",dp[m][0]);
            }
        }
        return 0;
    }
    
  • 相关阅读:
    动态链接库DLL
    异常处理
    内存
    线程同步
    线程基础、线程调度
    笔记摘录:进程、作业
    工具DebugView、PCHunter、Procexp、Procmon
    使用Windbg和VMware来搭建调试内核的环境
    C++智能指针
    AndroidEventBus
  • 原文地址:https://www.cnblogs.com/keyboarder-zsq/p/5934403.html
Copyright © 2011-2022 走看看