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.

Examples

Input
3 2
1 2 3
Output
2 3 4 5 6
Input
5 5
1 1 1 1 1
Output
5
Input
3 3
3 5 11
Output
9 11 13 15 17 19 21 25 27 33

题意:给定N个数a[],让你选择K个数,可以重复选,求其组合成的和有哪些。N、K、a[]<=1000;

思路:看成1000000项的多项式,如果存在a[]=x,则x的系数为1,然后多项式自乘K次,系数不为0的部分表示可以有K个数构成,可以用FFT+快速幂,为了避免精度误差,每次快速幂后把非0的改为1,免得变得很大后产生误差,复杂度O(1000000*log1000000*logK),有点大,稍微优化下常数可以卡过。

这里尝试 用NTT,由于系数可以达到1000^1000,所以需要除Mod,但是避免除一个Mod恰好变为0,所以我们取两个Mod避免hack。

快速幂+NTT   4398ms:

#include<bits/stdc++.h>
#define rep(i,x,y) for(int i=x;i<=y;i++)
using namespace std;
#define MOD Mod
#define ll long long
const int G=;
const int maxn=;
int Mod;
int qpow(int v,int p)
{
int ans=;
for(;p;p>>=,v=1ll*v*v%Mod)
if(p&)ans=1ll*ans*v%Mod;
return ans;
}
void rader(int y[], int len) {
for(int i=,j=len/;i<len-;i++) {
if(i<j) swap(y[i],y[j]);
int k=len/;
while(j>=k) j-=k,k/=;
if(j<k) j+=k;
}
}
void NTT(int y[],int len,int opt) {
rader(y,len);
for(int h=;h<=len;h<<=) {
int wn=qpow(G,(MOD-)/h);
if(opt==-) wn=qpow(wn,Mod-);
for(int j=;j<len;j+=h) {
int w=;
for(int k=j;k<j+h/;k++) {
int u=y[k];
int t=(ll)w*y[k+h/]%MOD;
y[k]=(u+t)%MOD;
y[k+h/]=(u-t+MOD)%MOD;
w=(ll)w*wn%MOD;
}
}
}
if(opt==-) {
int t=qpow(len,MOD-);
for(int i=;i<len;i++) y[i]=(ll)y[i]*t%MOD;
}
}
void powNTT(int ans[],int a[],int x)
{
ans[]=;int len=;
while(x){
len<<=;
if(x&){
NTT(ans,len,); NTT(a,len,);
rep(i,,len-) ans[i]=(ll)ans[i]*a[i]%Mod;
NTT(ans,len,-); NTT(a,len,-);
}
NTT(a,len,);
rep(i,,len-) a[i]=(ll)a[i]*a[i]%Mod;
NTT(a,len,-);
x>>=;
}
}
int A[maxn],B[maxn],ans1[maxn],ans2[maxn];
int main()
{
int N,K,x;
scanf("%d%d",&N,&K);
rep(i,,N) scanf("%d",&x),A[x]=,B[x]=;
Mod=; powNTT(ans1,A,K);
Mod=; powNTT(ans2,B,K);
rep(i,,) if(ans1[i]||ans2[i]) printf("%d ",i);
return ;
}

洛谷给出的代码,https://www.luogu.org/problemnew/solution/CF632E ,只一次NTT,在DFT后把每个数单自求pow(K),就得到了正确答案。

(暂时不理解其解法的正确性,如果是正确的,其NTT的写法里可能也有玄机(因为把这个NTT板子套其他题,样例过不了),尚待解决。

#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<=b;i++)
using namespace std;
#define ll long long
const int G=;
const int maxn=;
int mod,n,k,rev[maxn],lim,ilim,s,wn[maxn+];
std::vector<int> v;
inline int pow(int x, int y) {
int ans=;
for(;y;y>>=,x=(ll)x*x%mod)
if(y&) ans=(ll)ans*x%mod;
return ans;
}
inline int& up(int& x, int y) { if ((x+=y)>=mod) x-=mod; return x; }
inline void NTT(int* A, int typ) {
rep(i,,lim-) if (i<rev[i]) swap(A[i], A[rev[i]]);
for (int i=;i<lim;i+=i) {
const int t=lim/i/;
for (int j=;j<lim;j+=i+i) {
for (int k=;k<i; k++) {
int w=typ?wn[t*k]:wn[lim-t*k];
int x=A[k+j],y=(ll)w*A[k+j+i]%mod;
up(A[k+j],y),up(A[k+j+i]=x,mod-y);
}
}
}
if (!typ) rep(i,,lim-) A[i]=(ll)ilim*A[i]%mod;
}
inline void init(int len,int tmod) {
mod=tmod; lim=; s=-;
while(lim<len) lim+=lim,s++; ilim=pow(lim,mod-);
rep(i,,lim-) rev[i]=rev[i>>]>>|(i&)<<s;
int w=pow(G,(mod-)/len);
wn[]=;
rep(i,,lim) wn[i]=(ll)(wn[i-])*w%mod;
}
int A[maxn], B[maxn];
int main() {
scanf("%d%d",&n,&k);
int x; rep(i,,n) scanf("%d",&x), A[x]=B[x]=;
init(, );
NTT(A, );
rep(i,,lim-) A[i]=pow(A[i],k);
NTT(A, );
rep(i,,) if (A[i]) v.push_back(i);
init(, );
NTT(B, );
for (int i = ; i < lim; i++) B[i] = pow(B[i], k);
NTT(B, );
rep(i,,) if (B[i]) v.push_back(i);
sort(v.begin(), v.end()); int tot=unique(v.begin(), v.end())-v.begin();
v.resize(tot);
for (int i : v) printf("%d ",i);
return ;
}

CF632E: Thief in a Shop(快速幂+NTT)(存疑)的更多相关文章

  1. CF1096. G. Lucky Tickets(快速幂NTT)

    All bus tickets in Berland have their numbers. A number consists of n digits (n is even). Only k dec ...

  2. BZOJ 3992: [SDOI2015]序列统计 快速幂+NTT(离散对数下)

    3992: [SDOI2015]序列统计 Description 小C有一个集合S,里面的元素都是小于M的非负整数.他用程序编写了一个数列生成器,可以生成一个长度为N的数列,数列中的每个数都属于集合S ...

  3. CF632E Thief in a Shop 和 CF958F3 Lightsabers (hard)

    Thief in a Shop n个物品每个价值ai,要求选k个,可以重复.问能取到哪几个价值? 1 ≤ n, k ≤ 1000,1 ≤ ai ≤ 1000 题解 将选一个物品能取到的价值的01生成函 ...

  4. [CF632E]Thief in a Shop

    题目大意:有一个小偷,拿$k$个东西,有$n$种产品,每种产品都有无限多个.对于每个第$i$ 种产品,它的价值是$A_i$.可能偷走的物品价值之和. 题解:对于所有的物品构造生成函数$F(x)=\su ...

  5. BZOJ 3992 DP+NTT+快速幂

    思路: 普通的DP很好想吧 f[i][j]+=f[i-1][j*s[k]]  前i个数  mod m=j 的个数 m是质数  模数是质数  这就很有趣了 那么我们就求出来原根  所有的数都取指数 搞出 ...

  6. Codeforces632E Thief in a Shop(NTT + 快速幂)

    题目 Source http://codeforces.com/contest/632/problem/E Description A thief made his way to a shop. As ...

  7. 2018.12.31 bzoj3992: [SDOI2015]序列统计(生成函数+ntt+快速幂)

    传送门 生成函数简单题. 题意:给出一个集合A={a1,a2,...as}A=\{a_1,a_2,...a_s\}A={a1​,a2​,...as​},所有数都在[0,m−1][0,m-1][0,m− ...

  8. bzoj 3992 [SDOI2015]序列统计——NTT(循环卷积&&快速幂)

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3992 有转移次数.模M余数.方案数三个值,一看就是系数的地方放一个值.指数的地方放一个值.做 ...

  9. 【BZOJ3992】[SDOI2015]序列统计 NTT+多项式快速幂

    [BZOJ3992][SDOI2015]序列统计 Description 小C有一个集合S,里面的元素都是小于M的非负整数.他用程序编写了一个数列生成器,可以生成一个长度为N的数列,数列中的每个数都属 ...

随机推荐

  1. The 2018 ACM-ICPC上海大都会赛 J Beautiful Numbers (数位DP)

    题意:求小于等于N且能被自己所有位上数之和整除的数的个数. 分析:裸的数位dp.用一个三位数组dp[i][j][k]记录:第i位,之前数位之和为j,对某个mod余数为k的状态下满足条件的个数.这里mo ...

  2. canvas 事件绑定

    Canvas事件绑定   canvas事件绑定 众所周知canvas是位图,在位图里我们可以在里面画各种东西,可以是图片,可以是线条等等.那我们想给canvas里的某一张图片添加一个点击事件该怎么做到 ...

  3. linux中shell变量$#,$@,$0,$1,$2的含义

    linux中shell变量$#,$@,$0,$1,$2的含义解释: 变量说明: $$ Shell本身的PID(ProcessID) $! Shell最后运行的后台Process的PID $? 最后运行 ...

  4. JavaScript判断对象 是什么类型的.

    // 这种方法不起作用 if (x == undefined) {   // 作某些操作 } // 这个方法同样不起作用- if (typeof(x) == undefined) {   // 作某些 ...

  5. SVN使用—高级用法

    一.SVN分支 Branch 选项会给开发者创建出另外一条线路.当有人希望开发进程分开成两条不同的线路时,这个选项会非常有用. 情景: 比如项目 demo 下有两个小组,svn 下有一个 trunk ...

  6. Percona-Server-5.7.16 启动错误

    基于:percona-server-5.7.16 启动报错:  [root@monitor mysql]# ./bin/mysqld_safe --defaults-file=/data/config ...

  7. BigDecimal相关整理

    bigdecimal类型四则运算: BigDecimal s = new Bigdecimal(5); BigDecimal x = new Bigdecimal(15); 依次为最基础的加减乘除: ...

  8. 1044: [HAOI2008]木棍分割

    1044: [HAOI2008]木棍分割 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 2161  Solved: 779[Submit][Statu ...

  9. 防盗链&CSRF&API接口幂等性设计

    防盗链技术 CSRF(模拟请求) 分析防止伪造Token请求攻击 互联网API接口幂等性设计 忘记密码漏洞分析 1.Http请求防盗链 什么是防盗链 比如A网站有一张图片,被B网站直接通过img标签属 ...

  10. ThinkPHP关于模板的一些嵌套、IF判断使用

    > ##### 前言,现在有一组数据(涉及到3个数据表,order订单表,order_process办理流程表,process_status流程描述表),根据当前订单,展示相应信息 1.办理流程 ...