题意: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. php curl语句的用法

    system32文件夹下,修改php.ini文件,找到;extension= php_curl.dll行,去掉前面的;号,保存,重启服务器.在站点目录下建立一个PHP文件,内容如下 $ch = cur ...

  2. PHP中Array关于数组的用法

    使用函数array_keys(),得到数组中所有的键,参数:数组 $arr=array();$arr['one']="one";$arr['two']="two" ...

  3. PHP多表取数据的代码优化

    <?php header("Content-type: text/html; charset=utf-8"); //假设这里的$goods_arr  和 $shop_arr  ...

  4. java 字符串处理

    第一张: 第二张:

  5. 教你ECSHOP去版权与标志(新增272版)

    前台部分: 1:去掉头部TITLE部分的ECSHOP演示站 Powered by ecshop 前者在后台商店设置 - 商店标题修改 后者打开includes/lib_main.php $page_t ...

  6. meta标签部分总结

    <meta>标签用于提供页面的元信息,比如针对搜索引擎和更新频度的描述和关键词.由于看到很多网页<head>里面<meta>标签的内容很多,对这些标签含义了解不太清 ...

  7. YTU 2974: C语言习题5.26--文件操作3

    2974: C语言习题5.26--文件操作3 时间限制: 1 Sec  内存限制: 128 MB 提交: 213  解决: 92 题目描述 文本文件score.dic 中存储了n名学生的信息(班级编号 ...

  8. (jdbc)取得数据库自动生成的主键方法

    一些类,在前面的博客中有,就不重复了 public class Test2 { TestDAO t=new TestDAO(); /*前提是数据表的主键是自动增加的, *取得数据库自动生成的主键 * ...

  9. Sql Server 2008完全卸载方法(其他版本类似)

    一.    SQL2008卸载. 1.从控制面板卸载 1)点击计算机右下角“开始”,点击“控制面板” 2)点击“卸载程序”. 3)在程序列表中找到“Microsoft SQL Server 2008” ...

  10. Form1是父,form2是子,2的出现(覆盖在1的上面)不耽误1的操作

    //在form1的点击事件中 form2 f2=new form2(); f2.owner=this;//很重要 f2.show();