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 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
3 2
1 2 3
2 3 4 5 6
5 5
1 1 1 1 1
5
3 3
3 5 11
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)(存疑)的更多相关文章
- 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(离散对数下)
3992: [SDOI2015]序列统计 Description 小C有一个集合S,里面的元素都是小于M的非负整数.他用程序编写了一个数列生成器,可以生成一个长度为N的数列,数列中的每个数都属于集合S ...
- CF632E Thief in a Shop 和 CF958F3 Lightsabers (hard)
Thief in a Shop n个物品每个价值ai,要求选k个,可以重复.问能取到哪几个价值? 1 ≤ n, k ≤ 1000,1 ≤ ai ≤ 1000 题解 将选一个物品能取到的价值的01生成函 ...
- [CF632E]Thief in a Shop
题目大意:有一个小偷,拿$k$个东西,有$n$种产品,每种产品都有无限多个.对于每个第$i$ 种产品,它的价值是$A_i$.可能偷走的物品价值之和. 题解:对于所有的物品构造生成函数$F(x)=\su ...
- BZOJ 3992 DP+NTT+快速幂
思路: 普通的DP很好想吧 f[i][j]+=f[i-1][j*s[k]] 前i个数 mod m=j 的个数 m是质数 模数是质数 这就很有趣了 那么我们就求出来原根 所有的数都取指数 搞出 ...
- Codeforces632E Thief in a Shop(NTT + 快速幂)
题目 Source http://codeforces.com/contest/632/problem/E Description A thief made his way to a shop. As ...
- 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− ...
- bzoj 3992 [SDOI2015]序列统计——NTT(循环卷积&&快速幂)
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3992 有转移次数.模M余数.方案数三个值,一看就是系数的地方放一个值.指数的地方放一个值.做 ...
- 【BZOJ3992】[SDOI2015]序列统计 NTT+多项式快速幂
[BZOJ3992][SDOI2015]序列统计 Description 小C有一个集合S,里面的元素都是小于M的非负整数.他用程序编写了一个数列生成器,可以生成一个长度为N的数列,数列中的每个数都属 ...
随机推荐
- 理解display中的box-flex属性
今天有个同学在面试的时候碰到了使用css2和css3实现一种页面布局,要求页面效果如下: 在实现这种页面布局时,他使用了display:box-flex,下面是相应的代码: css2 方式 <! ...
- CWinApp类CMultiDocTemplate类CDocument类CView类的关系
转自:http://blog.csdn.net/bboot/article/details/26884011 不得不转,瞬间搞清了很多问题,短小精悍 1.CWinApp类 它包含并管理着应用程序的 ...
- NIO复习01
NIO 概述: 1. Java NIO 由以下几个核心部分组成:Channels Buffers Selectors 2. 主要Channel的实现:FileChann ...
- 开源CMDB详细安装使用
CMDB的GitHub地址: https://github.com/open-cmdb/cmdb 环境说明 [root@WCY ~]# cat /etc/redhat-release CentOS L ...
- 在阿里云centos7上搭建openvpn(未成功)
1.环境: 运行环境:阿里云 系统:centos 内核版本:-.el7.x86_64 各软件版本: iptables--.el7.x86_64 openvpn--.el7.x86_64 easy-rs ...
- 偶然发现有的IIS里的程序,连接 不上SQL Server数据库, 超时
经查应用程序池中, 有一个启用32位应用程序, 有时打开它就能连接上SQL SERVER了.
- LongestValidParentheses, 求最长合法括号子串长度-----同类问题ValidParentheses,GenerateParentheses
问题描述:求括号字符串中最长合法子串长度.例如:()((),返回2,而不是4. 算法分析:还是利用栈,和判断合法括号对是一样的. public static int longestValidParen ...
- 需要记忆的几个sql语句
链接查询: 1.查询两个表,在where中定义连接条件: select student.sno,sname,ssex,sage,sdept,cno,grade. from student,sc whe ...
- dypedef 和 define
typedef char *String_t; 和 #define String_dchar * 这两句在使用上有什么区别? 答:typedef char *String_t 定义了一个新的类型别名, ...
- ubuntu16.04 安装OpenNI并运行kinnectfusion
由于OpenNI是ubuntu12.04以前使用的驱动kinnect的库,现在用起来有很多的不便,用心的系统运行旧的设备,有诸多问题.现总结流程如下: 环境:Ubuntu16.04 64bit Kin ...