思路 :严格的控制好k的这个数量,这就是个裸完全背包问题.(复杂度最极端会到1e9)
他们随意原来随意组合的方案,与他们都减去 最小的 一个 a[ i ] 组合的方案数目是不会改变的
那么我们就 dp [ i ]表示 i 这个价格需要的最少 个数。 这样求最小个数保证不会漏解
然后 如果这个 i 能通过 1 - k 个物品组合出来,那么 一定能通过k 个物品组合出 i + k * a [ 1 ].
#include<bits/stdc++.h> using namespace std; #define ll long long #define inf 0x3f3f3f3f #define maxn 1234567 int n,k,dp[maxn],a[maxn]; int v[maxn],mi,sum,id,base; map<int,bool>vis; vector<int>ans; int main() { scanf("%d%d",&n,&k); for(int i=1; i<=n; i++) { scanf("%d",&a[i]); if(vis[a[i]]==0) { vis[a[i]]=1; v[++id]=a[i]; } } sort(v+1,v+1+id); base=v[1]*k; for(int i=2; i<=id; i++) v[i]-=v[1]; sum=v[id]*k; memset(dp,inf,sizeof(dp)); dp[0]=0; for(int i=2; i<=id; i++) for(int j=v[i]; j<=sum; j++) dp[j]=min(dp[j],dp[j-v[i]]+1); for(int i=0; i<=sum; i++) { if(dp[i]>k)continue; ans.push_back(i+base); } int len=ans.size(); for(int i=0; i<len; i++) { printf("%d",ans[i]); if(i<len-1)printf(" "); else printf("\n"); } return 0; }
思路:最初有的ai 初始化系数为1进行操作k次卷积。注意补零操作,然后注意最大长度,
也就是最终结果可能得到的最大指数 ....
#include <stdio.h> #include <string.h> #include <iostream> #include <algorithm> #include <math.h> #include <cstring> #include <cmath> using namespace std; const double PI = acos(-1.0); struct complex { double r,i; complex(double _r = 0.0,double _i = 0.0) { r = _r; i = _i; } complex operator +(const complex &b) { return complex(r+b.r,i+b.i); } complex operator -(const complex &b) { return complex(r-b.r,i-b.i); } complex operator *(const complex &b) { return complex(r*b.r-i*b.i,r*b.i+i*b.r); } }; void change(complex y[],int len) { int i,j,k; for(i = 1, j = len/2; i < len-1; i++) { if(i < j)swap(y[i],y[j]); k = len/2; while( j >= k) { j -= k; k /= 2; } if(j < k) j += k; } } void fft(complex y[],int len,int on) { change(y,len); for(int h = 2; h <= len; h <<= 1) { complex wn(cos(-on*2*PI/h),sin(-on*2*PI/h)); for(int j = 0; j < len; j+=h) { complex w(1,0); for(int k = j; k < j+h/2; k++) { complex u = y[k]; complex t = w*y[k+h/2]; y[k] = u+t; y[k+h/2] = u-t; w = w*wn; } } } if(on == -1) for(int i = 0; i < len; i++) y[i].r /= len; } const int MAXN = 5234567; complex x1[MAXN],x2[MAXN]; char str1[MAXN/2],str2[MAXN/2]; int sum[MAXN]; int siz[1100]; int main() { int n,k; scanf("%d %d", &n, &k); int x; int MAX = 0; memset(siz,0,sizeof(siz)); for(int i = 1; i <= n; i++) { scanf("%d", &x); siz[x] = 1; MAX = max(MAX,x); } int len1 = MAX * k; int len = 1; while(len < len1) len <<= 1; for(int i = 0; i < len; i++) x1[i] = complex(siz[i],0); x2[0] = complex(1,0); for(int i=1; i < len; i++) x2[i] = complex(0,0); fft(x1,len,1); fft(x2,len,1); while(k) { if(k % 2 == 1) { for(int i = 0; i <len; i++) x2[i] = x1[i]*x2[i]; fft(x2,len,-1); for(int i = 0; i < len; i++) { sum[i] = (int)(x2[i].r + 0.5); if(sum[i])x2[i]=complex(1,0); else x2[i]=complex(0,0); } fft(x2,len,1); } for(int i =0; i < len; i++) x1[i] = x1[i]*x1[i]; fft(x1,len,-1); for(int i = 0; i < len; i++) { sum[i] = (int)(x1[i].r + 0.5); if(sum[i])x1[i]=complex(1,0); else x1[i]=complex(0,0); } fft(x1,len,1); k /= 2; } fft(x2,len,-1); for(int i = 0; i < len; i++) { sum[i] = (int)(x2[i].r + 0.5); } for(int i = 0; i <len; i++) { if(sum[i]) printf("%d ",i); } return 0; }