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. pig(转载)

    本文可以让刚接触pig的人对一些基础概念有个初步的了解.本文大概是互联网上第一篇公开发表的且涵盖大量实际例子的Apache Pig中文教程(由Google搜索可知),文中的大量实例都是作者Darran ...

  2. Linux Shell编程 exit、break、continue

    exit语句 在系统中exit 命令用于退出当前用户的登录状态.在 Shell 脚本中exit 语句是用来退出当前脚本. exit 的语法如下: exit [返回值] 如果在 exit 之后定义了返回 ...

  3. dotnet new vue [C# 使用 vuejs]

    1. 安装 dotnet sdk 2.0 2. 安装 nodejs , npm 3. 安装淘宝镜像 4. 更新npm :   npm update -g 5. dotnet new -i vue 6. ...

  4. kafka和canal设置为开机启动

    1.切换到初始化目录 cd /etc/init.d/ 2.新建一个文件 如 touch autoupdate 3.vim autoupdate #!/bin/bash export JAVA_HOME ...

  5. scala学习手记16 – scala中的static

    前面两节学了scala的对象和伴生对象,这两个在使用的时候很有些java的静态成员的意思. scala中没有静态字段和静态方法.静态成员会破坏scala所支持的完整的面向对象模型.不过可以通过伴生对象 ...

  6. LeetCode第[55]题(Java):Jump Game

    题目:跳跳游戏 难度:Medium 题目内容: Given an array of non-negative integers, you are initially positioned at the ...

  7. 关于有时候Servlet会被执行两次的问题

    用<a>标签做了下载跳转,为什么点一次,servlet会被执行两次? 写了一个最简单的文件下载 点击超链接向servlet发送一个请求,然后下载该文件.可是每次该servlet都会被访问两 ...

  8. The 2014 ACM-ICPC Asia Mudanjiang Regional Contest

    The 2014 ACM-ICPC Asia Mudanjiang Regional Contest A.Average Score B.Building Fire Stations C.Card G ...

  9. shell 数组操作

    1. 定义数组: var_array=(one two three four five) 2.常用操作 获取数组长度: ${#var_array[@]} 获取所有数组元素:  ${var_array[ ...

  10. ASP.NET动态创建数据库和表

    using System; using System.Collections.Generic; using System.Data; using System.Data.SqlClient; usin ...