题意:dp[n] = ∑ ( dp[n-i]*a[i] )+a[n], ( 1 <= i < n)

cdq分治。

计算出dp[l ~ mid]后,dp[l ~ mid]与a[1 ~ r-l]做卷积运算。

 #include <bits/stdc++.h>
using namespace std;
const int N = 4e5+;
const int mod = ;
const double pi = acos(-1.0);
struct comp{
double r,i;comp(double _r=,double _i=){r=_r;i=_i;}
comp operator+(const comp x){return comp(r+x.r,i+x.i);}
comp operator-(const comp x){return comp(r-x.r,i-x.i);}
comp operator*(const comp x){return comp(r*x.r-i*x.i,r*x.i+i*x.r);}
}x[N], y[N];
void FFT(comp a[],int n,int t){
for(int i=,j=;i<n-;i++){
for(int s=n;j^=s>>=,~j&s;);
if(i<j)swap(a[i],a[j]);
}
for(int d=;(<<d)<n;d++){
int m=<<d,m2=m<<;
double o=pi/m*t;comp _w(cos(o),sin(o));
for(int i=;i<n;i+=m2){
comp w(,);
for(int j=;j<m;j++){
comp &A=a[i+j+m],&B=a[i+j],t=w*A;
A=B-t;B=B+t;w=w*_w;
}
}
}
if(t==-)for(int i=;i<n;i++)a[i].r/=n;
} int a[N], dp[N], n;
void cdq(int l,int r){
if(l == r){
dp[l] = (dp[l]+a[l])%mod;
return;
}
int mid = l+r >> ;
cdq(l, mid);
int len = ;
while(len <= (r-l+)) len <<= ;
for(int i = ; i < len; i++)
x[i] = y[i] = comp(, );
for(int i = l; i <= mid; i++)
x[i-l] = comp(dp[i], );
for(int i = ; l+i <= r; i++)
y[i-] = comp(a[i], );
FFT(x, len, ); FFT(y, len, );
for(int i = ; i < len; i++)
x[i] = x[i]*y[i];
FFT(x, len, -); for(int i = mid+; i <= r; i++){
dp[i] += x[i-l-].r+0.5;
dp[i] %= mod;
}
cdq(mid+,r);
} int main(){
while(scanf("%d", &n), n){
for(int i = ; i <= n; i++){
scanf("%d", a+i);
a[i] %= mod;
dp[i] = ;
}
cdq(, n);
printf("%d\n", dp[n]);
}
return ;
}

补:

因为做多项式逆运算在分治FFT之前,故做此题时首先有了一个多项式求逆的方法。

观察 dp[n] = ∑ ( dp[n-i]*a[i] )+a[n], ( 1 <= i < n)

令a[0] = -1, 则 ∑ ( dp[n-i]*a[i] )+a[n] = 0, ( 0 <= i < n) 对任意n > 0成立

令dp[0] = 1

则dp序列与a序列卷积 = dp[0]*a[0]  +  ∑ ( dp[i-j]*a[j] ) xi = dp[0]*a[0] = -1,

已知a序列,则dp序列为a的逆多项式序列*(-1)。

因为模313,最终各个系数 <= n(m-1)*(m-1) = 9734400000,  故选了一个大素数206158430209

写了一个多项式求逆的代码,不过不知什么原因WA了。

 #include<cstdio>
#include<iostream>
typedef long long ll;
using namespace std;
const int N = , K = ;
ll n, m, i, k;
ll a[N+], b[N+], tmp[N+], tmp2[N+];
ll P = 206158430209LL, G = , g[K+], ng[K+], inv[N+], inv2;
//ll P = 998244353, G = 3, g[K+1], ng[K+10], inv[N+10], inv2;
////////////
ll mul(ll a, ll b){
ll ans = ;
while(b){
if(b&) ans += a;
if(ans >= P) ans -= P;
a = a+a;
if(a >= P) a -= P;
b >>= ;
}
return ans;
}
ll pow(ll a, ll n){
ll ans = ;
while(n){
if(n&)
ans = mul(ans, a);
a = mul(a, a);
n >>= ;
}
return ans;
}
////////////
void NTT(ll*a,int n,int t){
for(int i=,j=;i<n-;i++){
for(int s=n;j^=s>>=,~j&s;);
if(i<j)swap(a[i], a[j]);
}
for(int d=;(<<d)<n;d++){
int m=<<d,m2=m<<;
ll _w=t==?g[d]:ng[d];/////////////////////////////////// for(int i=;i<n;i+=m2)for(ll w=,j=;j<m;j++){
ll&A=a[i+j+m],&B=a[i+j],t=mul(w, A);////////////(ll)w*A%P;
A=B-t;if(A<)A+=P;
B=B+t;if(B>=P)B-=P;
w=mul(w, _w);/////////(ll)w*_w%P;/////////////////////
}
}
//if(t==-1)for(int i=0,j=inv[n];i<n;i++)a[i]=mul(a[i], j);///////(ll)a[i]*j%P;
if(t==-){
ll j = pow(n, P-);
for(int i=;i<n;i++)a[i]=mul(a[i], j);
}
}
//给定a,求a的逆元b
void getinv(ll*a,ll*b,int n){
if(n==){b[]=pow(a[],P-);return;}
getinv(a,b,n>>);
int k=n<<,i;
for(i=;i<n;i++)tmp[i]=a[i];
for(i=n;i<k;i++)tmp[i]=b[i]=;
NTT(tmp,k,),NTT(b,k,); for(i=;i<k;i++){
ll xx = b[i];
b[i] = mul(xx, (P+-mul(xx, tmp[i]))%P);
//b[i]=(ll)b[i]*(2-(ll)tmp[i]*b[i]%P)%P;
//if(b[i]<0)b[i]+=P;
}
NTT(b,k,-);
for(i=n;i<k;i++)b[i]=;
}
int main(){
for(g[K]=pow(G,(P-)/N),ng[K]=pow(g[K],P-),i=K-;~i;i--){
//g[i]=(ll)g[i+1]*g[i+1]%P,ng[i]=(ll)ng[i+1]*ng[i+1]%P;
g[i] = mul(g[i+], g[i+]);
ng[i] = mul(ng[i+], ng[i+]);
}
//for(inv[1]=1,i=2;i<=N;i++)inv[i]=(ll)(P-inv[P%i])*(P/i)%P;inv2=inv[2];
while(scanf("%lld", &n), n){
int len = ;
while(len <= n) len <<= ;
//len <= 131072
a[] = (P-)%;
for(i = ; i <= n; i++){
scanf("%lld", a+i);
a[i] %= ;
}
for(i = n+; i < len; i++) a[i] = ; getinv(a, b, len);
b[n] = b[n]%*(P-1LL)%;
// for(i = 0; i < len; i++)
// b[i] = mul(b[i], P-1);
// b[i] = b[i]*(P-1LL)%P;
printf("%lld\n", b[n]);
}
return ;
}

HDU5730 FFT+CDQ分治的更多相关文章

  1. hdu 5830 FFT + cdq分治

    Shell Necklace Time Limit: 16000/8000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)T ...

  2. [玲珑OJ1044] Quailty and Binary Operation (FFT+cdq分治)

    题目链接 题意:给定两个长度为n的数组a与长度为m的数组b, 给定一个操作符op满足 x op y = x < y ? x+y : x-y.  有q个询问,每次给出询问c,问:有多少对(i, j ...

  3. hdu 5730 Shell Necklace fft+cdq分治

    题目链接 dp[n] = sigma(a[i]*dp[n-i]), 给出a1.....an, 求dp[n]. n为1e5. 这个式子的形式显然是一个卷积, 所以可以用fft来优化一下, 但是这样也是会 ...

  4. BNUOJ 51279[组队活动 Large](cdq分治+FFT)

    传送门 大意:ACM校队一共有n名队员,从1到n标号,现在n名队员要组成若干支队伍,每支队伍至多有m名队员,求一共有多少种不同的组队方案.两个组队方案被视为不同的,当且仅当存在至少一名队员在两种方案中 ...

  5. HDU 5730 Shell Necklace cdq分治+FFT

    题意:一段长为 i 的项链有 a[i] 种装饰方式,问长度为n的相连共有多少种装饰方式 分析:采用dp做法,dp[i]=∑dp[j]*a[i-j]+a[i],(1<=j<=i-1) 然后对 ...

  6. HDU 5730 Shell Necklace(CDQ分治+FFT)

    [题目链接] http://acm.hdu.edu.cn/showproblem.php?pid=5730 [题目大意] 给出一个数组w,表示不同长度的字段的权值,比如w[3]=5表示如果字段长度为3 ...

  7. 【BZOJ3456】轩辕朗的城市规划 无向连通图计数 CDQ分治 FFT 多项式求逆 多项式ln

    题解 分治FFT 设\(f_i\)为\(i\)个点组成的无向图个数,\(g_i\)为\(i\)个点组成的无向连通图个数 经过简单的推导(枚举\(1\)所在的连通块大小),有: \[ f_i=2^{\f ...

  8. 【CF553E】Kyoya and Train 最短路+cdq分治+FFT

    [CF553E]Kyoya and Train 题意:有一张$n$个点到$m$条边的有向图,经过第i条边要花$c_i$元钱,经过第i条边有$p_{i,k}$的概率要耗时k分钟.你想从1走到n,但是如果 ...

  9. Shell Necklace (dp递推改cdq分治 + fft)

    首先读出题意,然后发现这是一道DP,我们可以获得递推式为 然后就知道,不行啊,时间复杂度为O(n2),然后又可以根据递推式看出这里面可以拆解成多项式乘法,但是即使用了fft,我们还需要做n次多项式乘法 ...

随机推荐

  1. session 加入redis的实现代码方式

    session,中文经常翻译为会话,其本来的含义是 指有始有终的一系列动作/消息,比如打电话时从拿起电话拨号到挂断电话这中间的一系列过程可以称之为一个session.有时候我们可以看到这样的话&quo ...

  2. 20145227 《Java程序设计》第8周学习总结

    20145227 <Java程序设计>第8周学习总结 教材学习内容总结 第十四章 NIO与NIO2 NIO即New IO.java从JDK1.4开始提供了NIO,在JAVA SE 7 中又 ...

  3. linux终端拖动鼠标总是产生ctrl+c

    是因为有道词典,打开有道词典设置,取消勾选取词划词里面的所有框框

  4. tomcat部署到根路径

    在Tomcat中部署war包很简单: 首先,直接把相应的war包放到$TOMCAT_HOME/webapps下,不用建目录: 然后,修改$TOMCAT_HOME/conf/server.xml,在Ho ...

  5. .Uva&LA部分题目代码

    1.LA 5694 Adding New Machine 关键词:数据结构,线段树,扫描线(FIFO) #include <algorithm> #include <cstdio&g ...

  6. JAVA基础知识之JVM-——通过反射查看类信息

    Class实例 当类被加载之后,JVM中就会生成一个Class实例,通过这个实例就可以访问JVM中的这个类.有三种方式可以获取Class对象 使用Class的静态方法forName(完整包名) 调用类 ...

  7. Windows手动添加开机启动项

    @方法1. 添加程序完整路径到注册表HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Run下 或者添加到HKEY_CURREN ...

  8. jar文件签名

    1.生成密钥: keytool -genkey -keystore key.keystore -alias key -validity 3650 将在当前目录下生成一个key.keystore文件, ...

  9. Objective-C之category

    http://blog.csdn.net/siemenliu/article/details/7835808

  10. 回车和换行在linux下和windows下

    今天,我总算搞清楚"回车"(carriage return)和"换行"(line feed)这两个概念的来历和区别了. 1.  在计算机还没有出现之前,有一种叫 ...