Codeforces632E Thief in a Shop(NTT + 快速幂)
题目
Source
http://codeforces.com/contest/632/problem/E
Description
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 2
1 2 3
5 5
1 1 1 1 1
3 3
3 5 11
Sample Output
2 3 4 5 6
5
9 11 13 15 17 19 21 25 27 33
分析
题目大概说给有n种价值各一的物品,每种数量都无限多,问取出k个物品能取出的物品价值和的所有情况。
用母函数解,价值为指数、存不存在为系数,构造多项式求k次幂即可。
这自然想到FFT+快速幂求,这样时间复杂度才够。
FFT直接求的话结果的系数最大到达10001000太爆炸了,当然也可以求一次卷积后非0指数重新赋值成1;不过我想着开头一次DFT结尾一次IDFT这样更快、更轻松点,所以用NTT了。。
我NTT模数取1004535809 WA在20,取998244353 WA在21。。看样子是系数取模后变为0了,数据叼叼的。。于是我就两个模数都取,然后4000多ms险过了。。
代码
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define MAXN 1048576 //const long long P=50000000001507329LL; // 190734863287 * 2 ^ 18 + 1
long long P=1004535809; // 479 * 2 ^ 21 + 1
//const long long P=998244353; // 119 * 2 ^ 23 + 1
const int G=3; long long mul(long long x,long long y){
return (x*y-(long long)(x/(long double)P*y+1e-3)*P+P)%P;
}
long long qpow(long long x,long long k,long long p){
long long ret=1;
while(k){
if(k&1) ret=mul(ret,x);
k>>=1;
x=mul(x,x);
}
return ret;
} long long wn[25];
void getwn(){
for(int i=1; i<=21; ++i){
int t=1<<i;
wn[i]=qpow(G,(P-1)/t,P);
}
} int len;
void NTT(long long y[],int op){
for(int i=1,j=len>>1,k; i<len-1; ++i){
if(i<j) swap(y[i],y[j]);
k=len>>1;
while(j>=k){
j-=k;
k>>=1;
}
if(j<k) j+=k;
}
int id=0;
for(int h=2; h<=len; h<<=1) {
++id;
for(int i=0; i<len; i+=h){
long long w=1;
for(int j=i; j<i+(h>>1); ++j){
long long u=y[j],t=mul(y[j+h/2],w);
y[j]=u+t;
if(y[j]>=P) y[j]-=P;
y[j+h/2]=u-t+P;
if(y[j+h/2]>=P) y[j+h/2]-=P;
w=mul(w,wn[id]);
}
}
}
if(op==-1){
for(int i=1; i<len/2; ++i) swap(y[i],y[len-i]);
long long inv=qpow(len,P-2,P);
for(int i=0; i<len; ++i) y[i]=mul(y[i],inv);
}
}
void Convolution(long long A[],long long B[],int n){
for(len=1; len<(n<<1); len<<=1);
for(int i=n; i<len; ++i){
A[i]=B[i]=0;
} NTT(A,1); NTT(B,1);
for(int i=0; i<len; ++i){
A[i]=mul(A[i],B[i]);
}
NTT(A,-1);
} long long A[MAXN],B[MAXN],C[MAXN];
long long cnt[MAXN]; int main(){
getwn();
int n,k,a;
scanf("%d%d",&n,&k);
int mx=0;
for(int i=0; i<n; ++i){
scanf("%d",&a);
++cnt[a];
mx=max(mx,a);
}
for(len=1; len<mx*k; len<<=1); memcpy(A,cnt,sizeof(cnt));
NTT(A,1);
memcpy(B,A,sizeof(B));
--k;
int tmp=k;
while(k){
if(k&1){
for(int i=0; i<len; ++i) B[i]=mul(A[i],B[i]);
}
for(int i=0; i<len; ++i) A[i]=mul(A[i],A[i]);
k>>=1;
}
NTT(B,-1); P=998244353;
getwn();
memcpy(A,cnt,sizeof(cnt));
NTT(A,1);
memcpy(C,A,sizeof(C));
k=tmp;
while(k){
if(k&1){
for(int i=0; i<len; ++i) C[i]=mul(A[i],C[i]);
}
for(int i=0; i<len; ++i) A[i]=mul(A[i],A[i]);
k>>=1;
}
NTT(C,-1); for(int i=0; i<len; ++i){
if(B[i] || C[i]) printf("%d ",i);
}
return 0;
}
Codeforces632E Thief in a Shop(NTT + 快速幂)的更多相关文章
- CF632E: Thief in a Shop(快速幂+NTT)(存疑)
A thief made his way to a shop. As usual he has his lucky knapsack with him. The knapsack can contai ...
- BZOJ 3992: [SDOI2015]序列统计 NTT+快速幂
3992: [SDOI2015]序列统计 Time Limit: 30 Sec Memory Limit: 128 MBSubmit: 1155 Solved: 532[Submit][Statu ...
- 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− ...
- Educational Codeforces Round 9 E. Thief in a Shop NTT
E. Thief in a Shop A thief made his way to a shop. As usual he has his lucky knapsack with him. Th ...
- bzoj 3992: [SDOI2015]序列统计【原根+生成函数+NTT+快速幂】
还是没有理解透原根--题目提示其实挺明显的,M是质数,然后1<=x<=M-1 这种计数就容易想到生成函数,但是生成函数是加法,而这里是乘法,所以要想办法变成加法 首先因为0和任何数乘都是0 ...
- BZOJ 3992 DP+NTT+快速幂
思路: 普通的DP很好想吧 f[i][j]+=f[i-1][j*s[k]] 前i个数 mod m=j 的个数 m是质数 模数是质数 这就很有趣了 那么我们就求出来原根 所有的数都取指数 搞出 ...
- codeforces632E. Thief in a Shop (dp)
A thief made his way to a shop. As usual he has his lucky knapsack with him. The knapsack can contai ...
- 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 ...
- bzoj 3992 [SDOI2015]序列统计——NTT(循环卷积&&快速幂)
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3992 有转移次数.模M余数.方案数三个值,一看就是系数的地方放一个值.指数的地方放一个值.做 ...
随机推荐
- 创建线注记LineElement
1.根据2点创建一条线 /// <summary> /// 创建线 /// </summary> /// <param name="pnt1"> ...
- Oracle开机自启动
linux下启动oracle su - oracle #用oracle用户登陆 sqlplus /nolog conn /as sysdba startup exit lsnrctl start ex ...
- 适配iOS10以及Xcode8
现在在苹果的官网上,我们已经可以下载到Xcode8的GM版本了,加上9.14日凌晨,苹果就要正式推出iOS10系统的推送了,在此之际,iOS10的适配已经迫在眉睫啦,不知道Xcode8 beat版本, ...
- R语言-处理异常值或报错的三个示例
博客总目录:http://www.cnblogs.com/weibaar/p/4507801.html Tuesday, March 31, 2015 之前用rvest帮人写了一个定期抓取amazon ...
- 【PHP发展史】PHP5.2 到 PHP5.6 中新增的功能详解
截至目前(2014.2), PHP 的最新稳定版本是 PHP5.5, 但有差不多一半的用户仍在使用已经不在维护的 PHP5.2, 其余的一半用户在使用 PHP5.3. 因为 PHP 那“集百家之长”的 ...
- PHP中如何在数组中随机抽取n个数据的值 - array_rand()?
PHP中如何在数组中随机抽取n个数据的值? 最佳答案 array_rand() 在你想从数组中取出一个或多个随机的单元时相当有用.它接受 input 作为输入数组和一个可选的参数 num_req,指明 ...
- Daily Scrum Meeting ——ThirdDay
一.Daily Scrum Meeting照片 二.Burndown Chart 三.项目进展 1.完成了github上的文档整理 Transcend/ActivityHelper 2.主界面侧滑框的 ...
- ReactiveCocoa源码拆分解析(二)
(整个关于ReactiveCocoa的代码工程可以在https://github.com/qianhongqiang/QHQReactive下载) 上面抽丝剥茧的把最主要的信号机制给分离开了.但在RA ...
- Reader与InputStream两个类中的read()的区别
InputStream类的read()方法是从流里面取出一个字节,他的函数原型是 int read(); ,Reader类的read()方法则是从流里面取出一个字符(一个char),他的函数原型也是 ...
- C# 构建XML(简单示例)
C# 构建XML的简单示例: var pars = new Dictionary<string, string> { {"url","https://www. ...