Educational Codeforces Round 9 E. Thief in a Shop dp fft
2016-03-02 22:49
411 查看
E. Thief in a Shop
题目连接:
http://www.codeforces.com/contest/632/problem/EDescription
A thief made his way to a shop.As usual he has his lucky knapsack with him. The knapsack can contain k objects. There are n kinds of products in the shop and an infinite number of products of each kind. The cost of one product of kind i is ai.
The thief is greedy, so he will take exactly k products (it's possible for some kinds to take several products of that kind).
Find all the possible total costs of products the thief can nick into his knapsack.
Input
The first line contains two integers n and k (1 ≤ n, k ≤ 1000) — the number of kinds of products and the number of products the thief will take.The second line contains n integers ai (1 ≤ ai ≤ 1000) — the costs of products for kinds from 1 to n.
Output
Print the only line with all the possible total costs of stolen products, separated by a space. The numbers should be printed in the ascending order.Sample Input
3 21 2 3
Sample Output
2 3 4 5 6Hint
题意
有n个数,然后这n个数里面选k个加起来问你一共能加出来多少种
题解:
多项式加法,加k次,问你最后的数是哪些,显然FFT模板,然后怼一波其实DP也是可以兹瓷的。
dp[i]表示最少用多少个非a[1]能够构成a[1]*k+i的。
DP代码
#include<bits/stdc++.h> using namespace std; const int maxn = 1e3+5; int n,k,a[maxn],dp[maxn*maxn]; int main() { scanf("%d%d",&n,&k); for(int i=1;i<=n;i++) scanf("%d",&a[i]); sort(a+1,a+1+n); n=unique(a+1,a+1+n)-(a+1); for(int i=2;i<=n;i++) a[i]=a[i]-a[1]; for(int i=1;i<=k*a ;i++) dp[i]=k+1; for(int i=2;i<=n;i++) for(int j=a[i];j<=k*a[i];j++) dp[j]=min(dp[j],dp[j-a[i]]+1); for(int i=0;i<=k*a ;i++) if(dp[i]<=k) printf("%d ",a[1]*k+i); return 0; }
FFT代码
#include<bits/stdc++.h> using namespace std; typedef long long LL; const int maxn = 1<<21; const double PI = acos(-1.0); struct Virt { double r,i; Virt(double r = 0.0,double i = 0.0) { this->r = r; this->i = i; } Virt operator + (const Virt &x) { return Virt(r+x.r,i+x.i); } Virt operator - (const Virt &x) { return Virt(r-x.r,i-x.i); } Virt operator * (const Virt &x) { return Virt(r*x.r-i*x.i,i*x.r+r*x.i); } }; //雷德算法--倒位序 void Rader(Virt F[],int len) { int j = len >> 1; for(int i=1; i<len-1; i++) { if(i < j) swap(F[i], F[j]); int k = len >> 1; while(j >= k) { j -= k; k >>= 1; } if(j < k) j += k; } } //FFT实现 void FFT(Virt F[],int len,int on) { Rader(F,len); for(int h=2; h<=len; h<<=1) //分治后计算长度为h的DFT { Virt wn(cos(-on*2*PI/h),sin(-on*2*PI/h)); //单位复根e^(2*PI/m)用欧拉公式展开 for(int j=0; j<len; j+=h) { Virt w(1,0); //旋转因子 for(int k=j; k<j+h/2; k++) { Virt u = F[k]; Virt t = w*F[k+h/2]; F[k] = u+t; //蝴蝶合并操作 F[k+h/2] = u-t; w = w*wn; //更新旋转因子 } } } if(on == -1) for(int i=0; i<len; i++) F[i].r /= len; } //求卷积 void Conv(Virt F[],Virt G[],int len) { FFT(F,len,1); FFT(G,len,1); for(int i=0; i<len; i++) F[i] = F[i]*G[i]; FFT(F,len,-1); } int mx = 0; bool dp[maxn]; bool a[maxn]; Virt K1[maxn],K2[maxn]; void multiply(bool *A,bool *B,int l) { int len = 1; while(len<=l+1)len*=2; for(int i=0;i<len;i++) { K1[i].r=A[i]; K1[i].i=0; K2[i].r=B[i]; K2[i].i=0; } Conv(K1,K2,len); for(int i=0;i<=len;i++) A[i]=K1[i].r>0.5; } void solve(int k) { if(k==0) { dp[0]=true; } else if(k%2==1) { solve(k-1); multiply(dp,a,mx); } else { solve(k/2); multiply(dp,dp,mx); } } int main() { int n,k; scanf("%d%d",&n,&k); for(int i=0;i<n;i++) { int x;scanf("%d",&x); a[x]=true;mx=max(mx,x); } mx*=k; solve(k); for(int i=1;i<=mx;i++) if(dp[i])printf("%d ",i); cout<<endl; }
相关文章推荐
- linux挂载空磁盘步骤
- Hive de 功能架构
- Linux系统运维——文件查找——2
- nginx如何查看版本号和编译参数
- Apache2.4配置
- web请求状态码
- Docker - How to create a custom database from docker mysql image
- 关于linux上使用vi时,方向键出现ABCD的个人总结
- 嵌入式笔试题(linux基础)
- hive修改分区表
- 常用的linux命令
- Shell字符操作命令——grep、sed、awk
- NetBeans下Tomcat无法查看web应用运行,报错:部署错误
- Virtual Box上安装CentOS7
- virtualbox搭建ubuntu server nginx+mysql+tomcat web服务器1 (未完待续)
- OpenLDAP主配置文件slapd.conf介绍
- linux~存储学习
- Linux下chkconfig命令详解
- 后台调用外部程序的完美实现(使用CreateDesktop建立隐藏桌面)
- 嵌入式Linux驱动学习之USART串口控制:基于AT91SAM9261EK