【LOJ6067】【2017 山东一轮集训 Day3】第三题 FFT
【LOJ6067】【2017 山东一轮集训 Day3】第三题 FFT
题目大意
给你 \(n,b,c,d,e,a_0,a_1,\ldots,a_{n-1}\),定义
x_k&=b\times c^{4k}+d\times c^{2k}+e\\
f(x)&=\sum_{i=0}^{n-1}a_ix^i
\end{align}
\]
求 \(f(x_0),f(x_1),\ldots,f(x_{n-1})\)。
对 \({10}^6+3\) 取模。
题解
直接多项式多点求值(显然)会TLE。
当 \(c=0\) 时:
x_k&=
\begin{cases}
b+d+e,&k=0\\
e,&k\neq 0\\
\end{cases}
\end{align}
\]
直接求就好了。
当 \(c\neq 0,b=0\) 时:
f(x_k)&=\sum_{i=0}^{n-1}a_i{(dc^{2k}+e)}^i\\
&=\sum_{i=0}^{n-1}a_i\sum_{j=0}^{i}{(dc^{2k})}^je^{i-j}\binom{i}{j}\\
&=\sum_{j=0}^{n-1}\frac{1}{j!}d^jc^{2kj}\sum_{i=j}^{n-1}i!a_ie^{i-j}\frac{1}{(i-j)!}\\
&=\sum_{j=0}^{n-1}\frac{1}{j!}d^jc^{2kj}\sum_{i=0}^{n-j-1}(n-i-1)!a_{n-i-1}e^{(n-i-1)-j}\frac{1}{((n-i-1)-j)!}\\
&=\sum_{j=0}^{n-1}\frac{1}{j!}d^jc^{2kj}g_j\\
&=\sum_{j=0}^{n-1}\frac{1}{j!}d^jc^{k^2-({k-j)}^2+j^2}g_j\\
&=c^{k^2}\sum_{j=0}^{n-1}\frac{1}{j!}d^jc^{j^2}g_j\frac{1}{c^{{(k-j)}^2}}
\end{align}
\]
当 \(c\neq 0,b\neq 0\) 时:
bc^{4k}+dc^{2k}+e&=b(c^{4k}+\frac{d}{b}c^{2k})+e\\
&=b(c^{4k}+\frac{d}{b}c^{2k}+{(\frac{d}{2b})}^2-{(\frac{d}{2b})}^2)+e\\
&=b{(c^{2k}+\frac{d}{2b})}^2-\frac{d^2}{4b}+e\\
&=b{(c^{2k}+d')}^2+e'\\
\end{align}
\]
然后用 \(d'\) 和 \(e'\) 替换原来的 \(d\) 和 \(e\):
f(x_k)&=\sum_{i=0}^{n-1}a_i{(b{(c^{2k}+d)}^2+e)}^i\\
&=\sum_{i=0}^{n-1}a_i\sum_{j=0}^{i}b^j{(c^{2k}+d)}^{2j}e^{i-j}\binom{i}{j}\\
&=\sum_{j=0}^{n-1}b^j{(c^{2k}+d)}^{2j}\frac{1}{j!}\sum_{i=j}^{n-1}a_ii!e^{i-j}\frac{1}{i-j}\\
&=\sum_{j=0}^{n-1}b^j{(c^{2k}+d)}^{2j}\frac{1}{j!}g_j\\
&=\sum_{j=0}^{n-1}b^j\frac{1}{j!}g_j\sum_{i=0}^{2j}c^{2ki}d^{2j-i}\binom{2j}{i}\\
&=\sum_{i=0}^{2n-2}c^{2ki}\frac{1}{i!}\sum_{j=\lceil\frac{i}{2}\rceil}^{n-1}\frac{(2j)!}{j!}b^jg_j\frac{1}{(2j-i)!}d^{2j-i}\\
&=\sum_{i=0}^{2n-2}c^{2ki}\frac{1}{i!}\sum_{2j\geq i}^{2n-2}\frac{(2j)!}{j!}b^jg_j\frac{1}{(2j-i)!}d^{2j-i}\\
&=\sum_{i=0}^{2n-2}c^{2ki}\frac{1}{i!}h_i\\
&=c^{k^2}\sum_{i=0}^{2n-2}\frac{1}{i!}c^{i^2}h_i\frac{1}{c^{{(i-k)}^2}}
\end{align}
\]
那些卷积都可以FFT(任意模数FFT)。
时间复杂度:\(O(n\log n)\)
代码
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cstdlib>
#include<ctime>
#include<utility>
#include<functional>
#include<cmath>
#include<vector>
#include<assert.h>
//using namespace std;
using std::min;
using std::max;
using std::swap;
using std::sort;
using std::reverse;
using std::random_shuffle;
using std::lower_bound;
using std::upper_bound;
using std::unique;
typedef long long ll;
typedef unsigned long long ull;
typedef std::pair<int,int> pii;
typedef std::pair<ll,ll> pll;
void open(const char *s){
#ifndef ONLINE_JUDGE
char str[100];sprintf(str,"%s.in",s);freopen(str,"r",stdin);sprintf(str,"%s.out",s);freopen(str,"w",stdout);
#endif
}
int rd(){int s=0,c,b=0;while(((c=getchar())<'0'||c>'9')&&c!='-');if(c=='-'){c=getchar();b=1;}do{s=s*10+c-'0';}while((c=getchar())>='0'&&c<='9');return b?-s:s;}
void put(int x){if(!x){putchar('0');return;}static int c[20];int t=0;while(x){c[++t]=x%10;x/=10;}while(t)putchar(c[t--]+'0');}
int upmin(int &a,int b){if(b<a){a=b;return 1;}return 0;}
int upmax(int &a,int b){if(b>a){a=b;return 1;}return 0;}
const ll p=1000003;
const int N=530000;
ll fp(ll a,ll b)
{
if(!b)
return 1;
b=(b%(p-1)+p-1)%(p-1);
ll s=1;
for(;b;b>>=1,a=a*a%p)
if(b&1)
s=s*a%p;
return s;
}
namespace fft
{
const int W=524288;
const ll M=1000;
typedef double db;
db pi=acos(-1);
struct cp
{
db x,y;
cp(db a=0,db b=0):x(a),y(b){}
};
cp operator +(cp a,cp b){return cp(a.x+b.x,a.y+b.y);}
cp operator -(cp a,cp b){return cp(a.x-b.x,a.y-b.y);}
cp operator *(cp a,cp b){return cp(a.x*b.x-a.y*b.y,a.x*b.y+a.y*b.x);}
cp operator /(cp a,int b){return cp(a.x/b,a.y/b);}
cp conj(cp a){return cp(a.x,-a.y);}
cp muli(cp a){return cp(-a.y,a.x);}
cp divi(cp a){return cp(a.y,-a.x);}
int rev[N];
cp *w[20];
void fft(cp *a,int n,int t)
{
for(int i=1;i<n;i++)
{
rev[i]=(rev[i>>1]>>1)|(i&1?n>>1:0);
if(rev[i]>i)
swap(a[rev[i]],a[i]);
}
for(int i=2,s=1;i<=n;i<<=1,s++)
for(int j=0;j<n;j+=i)
for(int k=0;k<i/2;k++)
{
cp u=a[j+k];
cp v=a[j+k+i/2]*w[s][k];
a[j+k]=u+v;
a[j+k+i/2]=u-v;
}
if(t==-1)
{
reverse(a+1,a+n);
for(int i=0;i<n;i++)
a[i]=a[i]/n;
}
}
void dft(db *a,db *b,cp *c,cp *d,int n)
{
static cp a1[N],a2[N];
for(int i=0;i<n;i++)
a1[i]=cp(a[i],b[i]);
fft(a1,n,1);
for(int i=0;i<n;i++)
a2[i]=conj(a1[i]);
reverse(a2+1,a2+n);
for(int i=0;i<n;i++)
{
c[i]=(a1[i]+a2[i])/2;
d[i]=divi(a1[i]-a2[i])/2;
}
}
void idft(db *a,db *b,cp *c,cp *d,int n)
{
static cp a1[N];
for(int i=0;i<n;i++)
a1[i]=c[i]+muli(d[i]);
fft(a1,n,-1);
for(int i=0;i<n;i++)
{
a[i]=a1[i].x;
b[i]=a1[i].y;
}
}
void init()
{
for(int i=1;i<=19;i++)
w[i]=new cp[1<<(i-1)];
for(int i=0;i<W/2;i++)
w[19][i]=cp(cos(2*pi/W*i),sin(2*pi/W*i));
for(int i=18;i>=1;i--)
for(int j=0;j<1<<(i-1);j++)
w[i][j]=w[i+1][j<<1];
}
void mul(ll *a,ll *b,ll *c,int n,int m,int l)
{
static db a1[N],a2[N],b1[N],b2[N],c1[N],c2[N],d1[N],d2[N];
static cp a3[N],a4[N],b3[N],b4[N],c3[N],c4[N],d3[N],d4[N];
int k=1;
while(k<=n+m)
k<<=1;
for(int i=0;i<k;i++)
a1[i]=a2[i]=b1[i]=b2[i]=0;
for(int i=0;i<=n;i++)
{
a[i]=(a[i]+p)%p;
a1[i]=a[i]/M;
a2[i]=a[i]%M;
}
for(int i=0;i<=m;i++)
{
b[i]=(b[i]+p)%p;
b1[i]=b[i]/M;
b2[i]=b[i]%M;
}
dft(a1,a2,a3,a4,k);
dft(b1,b2,b3,b4,k);
for(int i=0;i<k;i++)
{
c3[i]=a3[i]*b3[i];
c4[i]=a3[i]*b4[i];
d3[i]=a4[i]*b3[i];
d4[i]=a4[i]*b4[i];
}
idft(c1,c2,c3,c4,k);
idft(d1,d2,d3,d4,k);
for(int i=0;i<=l;i++)
c[i]=((ll)(c1[i]+0.5)%p*M%p*M%p+(ll)(c2[i]+0.5)%p*M%p+(ll)(d1[i]+0.5)%p*M%p+(ll)(d2[i]+0.5)%p)%p;
}
}
int n;
ll B,C,D,E;
ll a[N];
ll inv[N],fac[N],ifac[N];
void init()
{
inv[1]=fac[0]=fac[1]=ifac[0]=ifac[1]=1;
for(int i=2;i<=200000;i++)
{
inv[i]=-p/i*inv[p%i]%p;
inv[i]=(inv[i]+p)%p;
fac[i]=fac[i-1]*i%p;
ifac[i]=ifac[i-1]*inv[i]%p;
}
}
namespace pregao
{
ll b[N],c[N],s[N];
void gao()
{
for(int i=0;i<n;i++)
{
b[i]=a[n-i-1]*fac[n-i-1]%p;
c[i]=ifac[i]*fp(E,i)%p;
}
fft::mul(b,c,s,n-1,n-1,n-1);
reverse(s,s+n);
}
}
namespace gao1
{
ll d[N],e[N],f[N],g[N],h[N],ans[N];
void gao()
{
pregao::gao();
for(int i=0;i<n;i++)
{
d[i]=pregao::s[i]*fp(D,i)%p*fp(C,(ll)i*i)%p*ifac[i]%p;
e[i]=fp(C,-(ll)i*i);
}
fft::mul(d,e,f,n-1,n-1,n-1);
reverse(d,d+n);
e[0]=0;
fft::mul(d,e,g,n-1,n-1,n-1);
for(int i=0;i<n;i++)
{
ans[i]=((f[i]+g[n-i-1])%p+p)%p;
ans[i]=ans[i]*fp(C,(ll)i*i)%p;
}
for(int i=0;i<n;i++)
printf("%lld\n",ans[i]);
}
}
namespace gao2
{
ll b[N],c[N],d[N],e[N],f[N],g[N],ans[N];
void gao()
{
E=(E-D*D%p*fp(4*B,p-2)%p+p)%p;
D=D*fp(2*B,p-2)%p;
pregao::gao();
for(int i=0;i<n;i++)
b[2*n-2*i-2]=fac[2*i]*ifac[i]%p*pregao::s[i]%p*fp(B,i)%p;
for(int i=0;i<2*n-1;i++)
c[i]=fp(D,i)*ifac[i]%p;
fft::mul(b,c,d,2*n-2,2*n-2,2*n-2);
reverse(d,d+2*n-1);
for(int i=0;i<2*n-1;i++)
{
d[i]=d[i]*ifac[i]%p*fp(C,(ll)i*i)%p;
e[i]=fp(C,-(ll)i*i);
}
fft::mul(d,e,f,n-1,n-1,n-1);
reverse(d,d+2*n-1);
e[0]=0;
fft::mul(d,e,g,2*n-2,2*n-2,2*n-2);
for(int i=0;i<n;i++)
ans[i]=(fp(C,(ll)i*i)*(f[i]+g[2*n-i-2])%p+p)%p;
for(int i=0;i<n;i++)
printf("%lld\n",ans[i]);
}
}
namespace gao0
{
void gao()
{
ll ans=0;
for(int i=n-1;i>=0;i--)
{
ans=ans*(E+B+D)%p;
ans=(ans+a[i])%p;
}
printf("%lld\n",ans);
ans=0;
for(int i=n-1;i>=0;i--)
{
ans=ans*E%p;
ans=(ans+a[i])%p;
}
for(int i=1;i<n;i++)
printf("%lld\n",ans);
}
}
int main()
{
open("loj6067");
fft::init();
init();
scanf("%d%lld%lld%lld%lld",&n,&B,&C,&D,&E);
for(int i=0;i<n;i++)
a[i]=rd();
if(!C)
gao0::gao();
else if(!B)
gao1::gao();
else
gao2::gao();
return 0;
}
【LOJ6067】【2017 山东一轮集训 Day3】第三题 FFT的更多相关文章
- 【LOJ#6066】「2017 山东一轮集训 Day3」第二题(哈希,二分)
[LOJ#6066]「2017 山东一轮集训 Day3」第二题(哈希,二分) 题面 LOJ 题解 要哈希是很显然的,那么就考虑哈希什么... 要找一个东西可以表示一棵树,所以我们找到了括号序列. 那么 ...
- [LOJ#6066]. 「2017 山东一轮集训 Day3」第二题[二分+括号序列+hash]
题意 题目链接 分析 首先二分,假设二分的答案为 \(mid\),然后考虑利用括号序列来表示树的形态. 点 \(u\) 的 \(k-\) 子树的括号序列表示实际上是刨去了 \(u\) 子树内若干个与 ...
- LOJ6066:「2017 山东一轮集训 Day3」第二题
传送门 二分答案 \(k\),考虑如何 \(hash\) 使得做起来方便 把每个点挂在 \(k+1\) 级祖先上,考虑在祖先上删除 这道题巧妙在于其可以对于 \(dfs\) 序/括号序列 \(hash ...
- LOJ.6066.[2017山东一轮集训Day3]第二题(树哈希 二分)
LOJ 被一件不愉快的小事浪费了一个小时= =. 表示自己(OI方面的)智商没救了=-= 比较显然 二分+树哈希.考虑对树的括号序列进行哈希. 那么每个点的\(k\)子树的括号序列,就是一段区间去掉距 ...
- loj6100 「2017 山东二轮集训 Day1」第一题
传送门:https://loj.ac/problem/6100 [题解] 我们考虑维护从某个端点开始的最长满足条件的长度,如果知道了这个东西显然我们可以用主席树来对每个节点建棵关于右端点的权值线段树, ...
- Loj #6069. 「2017 山东一轮集训 Day4」塔
Loj #6069. 「2017 山东一轮集训 Day4」塔 题目描述 现在有一条 $ [1, l] $ 的数轴,要在上面造 $ n $ 座塔,每座塔的坐标要两两不同,且为整点. 塔有编号,且每座塔都 ...
- Loj #6073.「2017 山东一轮集训 Day5」距离
Loj #6073.「2017 山东一轮集训 Day5」距离 Description 给定一棵 \(n\) 个点的边带权的树,以及一个排列$ p\(,有\)q $个询问,给定点 \(u, v, k\) ...
- Loj 6068. 「2017 山东一轮集训 Day4」棋盘
Loj 6068. 「2017 山东一轮集训 Day4」棋盘 题目描述 给定一个 $ n \times n $ 的棋盘,棋盘上每个位置要么为空要么为障碍.定义棋盘上两个位置 $ (x, y),(u, ...
- 「2017 山东一轮集训 Day5」苹果树
「2017 山东一轮集训 Day5」苹果树 \(n\leq 40\) 折半搜索+矩阵树定理. 没有想到折半搜索. 首先我们先枚举\(k\)个好点,我们让它们一定没有用的.要满足这个条件就要使它只能和坏 ...
随机推荐
- WebService访问oracle数据库本地调试
WebService访问oracle数据库本地调试-一步一个坑 上篇文章提到我们额数据库挂了,重装了数据库,然后呢我需要在本地调试WebService,看看那些数据结构缺失,迁移到新数据库中去.踩坑之 ...
- c或c++利用scanf无限输入并进行简单操作如比大小等
#include <iostream> using namespace std; int main() { ; ) //scanf返回值为int类型表示成功输入的数据数量个数 { if(n ...
- Android入门第一课之Java基础
通知:由于本周六场地申请没通过,所以本周的培训临时取消. 今天给大家带来的是Android入门的第一课,由于教室申请的不确定性,因此,每次培训的内容都会在博客先提前释放出来.首先Android的APP ...
- Android studio设置文件头,定制代码注释
一.说明 在下载或者看别人的代码我们常会看见,每一个文件的上方有个所属者的备注.如果要是一个一个备注那就累死了. 二.设置方法 File >>> Setting >>&g ...
- 新更新,又是一年了。这次记录下关于android版的WeiboDemo的问题
时隔一年多,现在又开始折腾android的代码了.之前看了Learning android,就想看下能否移植到Weibo.然后就下了weibo的代码,代码包里有个实例叫WeiboSDKDemo. 为了 ...
- idea部署Maven入门(一)——环境变量的配置和下载
介绍: 1 Maven是用来管理jar包的一种工具, 2 Maven主要是构建java项目和java web项目 3 maven项目管理所依赖的jar ...
- 坚定关于考研或者工作的决定:work
转眼之间,我已经夸过了大二结束的节点,已经是一个准大三了: 在这个岔路口,首要的选择就是考研和工作的选择:我也有过犹豫要不要考研,最终还是放弃了考研的想法,从考研的利弊两个方面来谈: 首 ...
- JMeter接口测试 (二) ~ 参数化
对应qq群号:616961231 上篇内容介绍了jmeter的基本使用, 略微提了如何做参数化, 本篇对参数化做进一步深入讲解, 参数化可以将一个变量使用不同数据, 比如有多个用户下单购买商品,调用 ...
- linux FTP安全配置
linux FTP安全配置 关闭防火墙,selinux安全机制 service iptables stop setenforce 0 匿名用户 匿名用户只能访问ftp服务器上的/var/ftp/ ...
- 本机不安装Oracle客户端,使用PL/SQL Developer和 Instant Client 工具包连接oracle 11g远程数据库
一.先到Oracle网站下载Instant Client 下载地址:http://www.oracle.com/technetwork/cn/database/features/instant-cli ...