T89379 【qbxt】复读警告
题解
这是一道DP题
设置状态 f[ i ][ j ] 前 i 个数中所选数字之和 % key 得 j 的最大方案数
当前我们该选择第 i 个数字了,那么这个数字可以选也可以不选
不选 i 的话方案数直接由 f[ i-1 ][ j ] 转移过来
选 i 的话,选择前 i-1 个数字的时候 % key 的余数是 j-a[ i ]%key ,注意减完之后处理负数的情况
加法分类原理,转移方程:f[ i ][ j ] += f[ i-1 ][ j ] + f[ i-1 ][ t ]
边界条件:f[0][0]=1
ans = f[n][0]
代码
#include<iostream> #include<cstdio> #include<string> #include<cstring> #include<algorithm> #include<cmath> #include<cstdlib> #include<queue> using namespace std; inline int read() { int ans=0; char last=' ',ch=getchar(); while(ch<'0'||ch>'9') last=ch,ch=getchar(); while(ch>='0'&&ch<='9') ans=ans*10+ch-'0',ch=getchar(); if(last=='-') ans=-ans; return ans; } const int mod=1e9+7; int n,key; int a[1010]; int f[1010][1010]; int main() { n=read();key=read(); for(int i=1;i<=n;i++) a[i]=read(); f[0][0]=1; for(int i=1;i<=n;i++) for(int j=0;j<key;j++) { int t=j-a[i]%key; if(t<0) t=(t+key)%key; f[i][j]+=(f[i-1][j]+f[i-1][t])%mod; } printf("%d",f[n][0]%mod); return 0; }