LightOJ1125

来源:互联网 发布:蓝月亮 荧光剂 知乎 编辑:程序博客网 时间:2024/05/17 22:50

Divisible Group Sums

题目链接

分类:dp

1.题意概述

  • 给你n个数,要你从中挑选m个,使得它们的和能够被D整除。

2.解题思路

  • 标准的动态规划,用dp[i][j][k][mod]表示前i个数选了j个,除数为k,余数为mod的情况,那么下一步选择就是选或者不选,实际上这就是一个01背包问题,转移方程:
    • 选这个数dp[i][j][k][(a[j][k]+l)%k] += dp[i1][j1][k][l]
    • 不选这个数dp[i][j][k][l] += dp[i1][j][k][l]

3.AC代码

#include <bits/stdc++.h>#define INF 0x3f3f3f3f#define maxn 50010#define N 222#define eps 1e-6#define pi acos(-1.0)#define e exp(1.0)using namespace std;const int mod = 1e9 + 7;typedef long long ll;typedef unsigned long long ull;ll dp[11][22];int a[N], fac[N];int main(){#ifndef ONLINE_JUDGE    freopen("in.txt", "r", stdin);    freopen("out.txt", "w", stdout);    long _begin_time = clock();#endif    int t, n, q, kase = 0;    scanf("%d", &t);    while (t--)    {        scanf("%d%d", &n, &q);        printf("Case %d:\n", ++kase);        for (int i = 1; i <= n; i++)            scanf("%d", &a[i]);        while (q--)        {            int d, m;            scanf("%d%d", &d, &m);            for (int i = 1; i <= n; i++)                fac[i] = (a[i] % d + d) % d;            memset(dp, 0, sizeof(dp));            dp[0][0] = 1;            for (int i = 1; i <= n; i++)                for (int j = m; j > 0; j--)                    for (int k = 0; k < d; k++)                        dp[j][(k + fac[i]) % d] += dp[j - 1][k];            printf("%lld\n", dp[m][0]);        }    }#ifndef ONLINE_JUDGE    long _end_time = clock();    printf("time = %ld ms.", _end_time - _begin_time);#endif    return 0;}
原创粉丝点击