题意:给出n个数,找出若干个数,使它们的和为k的倍数,并输出最大的数。
状态转移方程:f[i][j]表示前i个数%k=j的总数。
f[i][j]=max(f[i-1][j],f[i-1][tmp]+a[i]);
tmp=(k+j-a[i]%k)%k(避免负数)
第一种情况不选第i个数,第二种情况为选这个数时的最优值
(当然要满足tmp=0或者f[i-1][tmp]有最优值)
#include<cstdio>
#include<algorithm>
using namespace std;
int a[101],n,k,f[101][101];
int main(){
scanf("%d%d",&n,&k);
for (int i=1;i<=n;i++) scanf("%d",&a[i]);
for (int i=1;i<=n;i++)
for (int j=0;j<k;j++){
f[i][j]=f[i-1][j];//不选的情况
int tmp=(k+j-a[i]%k)%k;//避免负数
if (!tmp||f[i-1][tmp]) f[i][j]=max(f[i][j],f[i-1][tmp]+a[i]);//推导
}
printf("%d",f[n][0]); //选n个数并且余数为0的最优值。
return 0;
}