传送门

这么一道水题我还用各种麻烦的方法去做……这人没救了

看在这题做法挺多的份上,我就都写写好了……

 

1.CDQ分治

这个做法是我想到的……因为受到了Eden的新背包问题的启发……

定义solve(l,r)表示删除编号在[l,r]的物品并计算其DP数组,显然这个是可以折半往下递归的,用没删掉的那一半更新一下DP数组并带着DP数组递归下去即可。

T(n)=2T(n/2)+O(nm),解得T(n)=O(nmlogn),并且比O(nm)的做法慢不了多少。

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 using namespace std;
 5 const int maxn=2010;
 6 void CDQ(int,int,int);
 7 int n,m,w[maxn],f[15][maxn]={{0}};
 8 int main(){
 9     scanf("%d%d",&n,&m);
10     for(int i=1;i<=n;i++)scanf("%d",&w[i]);
11     f[0][0]=1;
12     CDQ(1,n,0);
13     return 0;
14 }
15 void CDQ(int l,int r,int k){
16     if(l==r){
17         for(int i=1;i<=m;i++)printf("%d",f[k][i]);
18         printf("\n");
19         return;
20     }
21     int mid=(l+r)>>1;
22     copy(f[k],f[k]+m+1,f[k+1]);
23     for(int i=mid+1;i<=r;i++)for(int j=m;j>=w[i];j--){
24         f[k+1][j]+=f[k+1][j-w[i]];
25         if(f[k+1][j]>=10)f[k+1][j]%=10;
26     }
27     CDQ(l,mid,k+1);
28     copy(f[k],f[k]+m+1,f[k+1]);
29     for(int i=l;i<=mid;i++)for(int j=m;j>=w[i];j--){
30         f[k+1][j]+=f[k+1][j-w[i]];
31         if(f[k+1][j]>=10)f[k+1][j]%=10;
32     }
33     CDQ(mid+1,r,k+1);
34 }
View Code

相关文章:

  • 2022-02-07
  • 2022-12-23
  • 2021-10-28
  • 2021-12-23
  • 2021-09-07
  • 2021-10-27
  • 2022-12-23
  • 2022-02-21
猜你喜欢
  • 2021-08-17
  • 2021-07-11
  • 2021-08-18
  • 2022-12-23
  • 2021-04-21
  • 2021-11-19
  • 2021-08-03
相关资源
相似解决方案