给定一个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 0x3f3f3f3f ll 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; }