题意:

给你 n 个背包,然后给你两个数,D,M,问你从n个里面挑M个出来,有多少种方法能够整除D;





思路:



试想我先不挑M个出来的话,仅仅是构造一个D的倍数,其实就是构造一个数的话,

其实就是个递推,然后方案的叠加



挑M个,D的倍数。

能对M个状压;

但是对于D的倍数呢?

其实就是取膜就好了,比如5的倍数,

那么dp[个数][j]+=dp[个数-1][j-X];(个数都是状压了)



但是现在是200个里面挑10个啊。。。

不行的话就再加一维。

所以还是要从前 i 个物品推过来。。。

所以现在可以搞成dp[i][j][k]表示前i个物品选j个%D=k时的方案数;= =

每次逆推可以把第一维去掉,时间复杂度也OK;

总的来说就是:能状压么?不能解决这个事情就再开一维,一维不行上二维,二维不行三维先上了再说;(PS:n个里面选m个真是玄学。。第二遍做。。。还是碰壁GG。

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef unsigned long long ULL;
typedef pair<int,int>PII;
const double eps=1e-5;
const double pi=acos(-1.0);
const int INF=0x3f3f3f3f;
const int N=1e2+10; int a[N*2];
LL dp[12][25]; int main()
{
int cas=1;
int n,w,q,d,m;
int t,x,sum;
scanf("%d",&t);
while(t--)
{
scanf("%d%d",&n,&q);
for(int i=1;i<=n;i++)
scanf("%d",&a[i]); printf("Case %d:\n",cas++); for(int k=1;k<=q;k++)
{
scanf("%d%d",&d,&m);
memset(dp,0,sizeof(dp));
dp[0][0]=1LL;
for(int i=1;i<=n;i++)
{
int temp=a[i]%d;
for(int j=m;j>=1;j--)
for(int x=0;x<d;x++)
dp[j][x]+=dp[j-1][(x+d-temp)%d];
}
printf("%lld\n",dp[m][0]);
}
}
return 0;
}

最新文章

  1. Javascript和HTML:
  2. Scrapy003-项目流程
  3. performSelector和performSelectorInBackground
  4. ARP投毒及其防御方法
  5. shelve模块理解
  6. IOS NSDate NSDateFormatter 导致相差8小时
  7. C# DataContract DataMember
  8. rel=nofollow
  9. c++map按value排序--将map的pair对保存到vector中,然后写比较仿函数+sort完成排序过程。
  10. JS+CSS简单实现DIV遮罩层显示隐藏
  11. SQL Server删除表信息的三种方法
  12. vector 对象中存放指针类型数据
  13. dd的用法
  14. Vuforia开发完全指南---Vuforia概述
  15. 在Unity3D中利用 RenderTexture 实现游戏内截图
  16. 单片机开发——03工欲善其事必先利其器(AD软件安装破解)
  17. echarts中legend如何换行
  18. nginx多server配置记录
  19. U3D学习09-物体简单控制及视角观察
  20. 无法打开这些文件internet安全设置

热门文章

  1. switch中的case不加break执行情况
  2. OpenWrt:路由器上的Linux
  3. 官网下载kettle
  4. Drawing Images and Text
  5. EasyPlayer iOS开源流媒体播放器中AAC解码PCM问题
  6. aop学习总结三----aop的相关概念
  7. Spring 实战 学习笔记(1)
  8. objective-c的代码块block
  9. HTML5与php实现消息推送功能
  10. bzoj4670: 佛罗里达