lightoj 1125 - Divisible Group Sums 01背包变形

来源:互联网 发布:淘宝定制商品规则买家 编辑:程序博客网 时间:2024/05/22 01:26

给定一个n,q以及n个数字,代表有q次询问,每次询问一个d,m,选择m个数字(不可重复选)组成集合是d的倍数有多少种方法

q比较小可以先不考虑...

对于一个数字选与不选就构成01背包...选择了多少个数字当做背包体积吧...因为要求方案数,所以不能拿余数当做价值了...

得另外再开一维当做余数,那么选了确定x个数字后余数是多少也要顺便枚举一下吧...

注意,01背包的滚动数组体积那重循环是逆向的,所以选择多少数字那重循环也要逆向来...当然开成三维DP不需要考虑这个事情..

注意爆int..毕竟C(200,10)

#include<bits/stdc++.h>using namespace std;#define ll long long#define mod 1000000007#define inf 0x3f3f3f3fll dp[12][25];int a[300];int main(){    int t;    scanf("%d",&t);    for(int cas=1;cas<=t;cas++)    {        int n,q;        scanf("%d %d",&n,&q);        for(int i=1;i<=n;i++)            scanf("%d",&a[i]);        printf("Case %d:\n",cas);        while(q--)        {            int d,m;            scanf("%d %d",&d,&m);            memset(dp,0,sizeof(dp));            dp[0][0]=1LL;            for(int i=1;i<=n;i++)            {                int tmp=a[i]%d;                for(int j=m;j>=1;j--)                {                    for(int k=0;k<d;k++)                        dp[j][k]+=dp[j-1][(k+2*d-tmp)%d];                }            }            printf("%lld\n",dp[m][0]);        }    }    return 0;}


0 0
原创粉丝点击