【HDU5730】Shell Necklace(多项式运算,分治FFT)
【HDU5730】Shell Necklace(多项式运算,分治FFT)
题面
Vjudge
翻译:
有一个长度为\(n\)的序列
已知给连续的长度为\(i\)的序列装饰的方案数为\(a[i]\)
求将\(n\)个位置全部装饰的总方案数。
答案\(mod\ 313\)
题解
很明显,是要求:
\(f[n]=\sum_{i=0}^na[i]\times f[n-i],f[0]=0\)
卷积的形式啊。。
然后就可以开始搞了
忍不住的方法一
好明显啊,把生成函数\(F,A\)给搞出来
然后就有\(F*A+1=F\)
然后\((1-A)F=1\)
然后\(F=\frac{1}{1-A}\)
多项式求逆,没了。。。
但是这个\(mod\ 313\)很蛋疼啊。。
直接蒯模板了
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<set>
#include<map>
#include<vector>
#include<queue>
using namespace std;
#define ll long long
#define ull unsigned long long
#define RG register
#define MAX 288888
#define MOD (313)
const double Pi=acos(-1);
const int m=sqrt(MOD);
inline int read()
{
RG int x=0,t=1;RG char ch=getchar();
while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
if(ch=='-')t=-1,ch=getchar();
while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
return x*t;
}
int fpow(int a,int b){int s=1;while(b){if(b&1)s=1ll*s*a%MOD;a=1ll*a*a%MOD;b>>=1;}return s;}
struct Complex{double a,b;}W[MAX],A[MAX],B[MAX],C[MAX],D[MAX];
Complex operator+(Complex a,Complex b){return (Complex){a.a+b.a,a.b+b.b};}
Complex operator-(Complex a,Complex b){return (Complex){a.a-b.a,a.b-b.b};}
Complex operator*(Complex a,Complex b){return (Complex){a.a*b.a-a.b*b.b,a.a*b.b+a.b*b.a};}
int r[MAX];
void FFT(Complex *P,int N,int opt)
{
for(int i=0;i<N;++i)if(i<r[i])swap(P[i],P[r[i]]);
for(int i=1;i<N;i<<=1)
for(int p=i<<1,j=0;j<N;j+=p)
for(int k=0;k<i;++k)
{
Complex w=(Complex){W[N/i*k].a,W[N/i*k].b*opt};
Complex X=P[j+k],Y=P[i+j+k]*w;
P[j+k]=X+Y;P[i+j+k]=X-Y;
}
if(opt==-1)for(int i=0;i<N;++i)P[i].a/=1.0*N;
}
void Multi(int *a,int *b,int len,int *ret)
{
for(int i=0;i<(len<<1);++i)A[i]=B[i]=C[i]=D[i]=(Complex){0,0};
for(int i=0;i<len;++i)
{
a[i]%=MOD;b[i]%=MOD;
A[i]=(Complex){(a[i]/m)*1.0,0};
B[i]=(Complex){(a[i]%m)*1.0,0};
C[i]=(Complex){(b[i]/m)*1.0,0};
D[i]=(Complex){(b[i]%m)*1.0,0};
}
int N,l=0;
for(N=1;N<=len;N<<=1)++l;
for(int i=0;i<N;++i)r[i]=(r[i>>1]>>1)|((i&1)<<(l-1));
for(int i=1;i<N;i<<=1)
for(int k=0;k<i;++k)W[N/i*k]=(Complex){cos(k*Pi/i),sin(k*Pi/i)};
FFT(A,N,1);FFT(B,N,1);FFT(C,N,1);FFT(D,N,1);
for(int i=0;i<N;++i)
{
Complex tmp=A[i]*C[i];
C[i]=B[i]*C[i],B[i]=B[i]*D[i],D[i]=D[i]*A[i];
A[i]=tmp;C[i]=C[i]+D[i];
}
FFT(A,N,-1);FFT(B,N,-1);FFT(C,N,-1);
for(int i=0;i<len;++i)
{
ret[i]=0;
ret[i]=(ret[i]+1ll*(ll)(A[i].a+0.5)%MOD*m%MOD*m%MOD)%MOD;
ret[i]=(ret[i]+1ll*(ll)(C[i].a+0.5)%MOD*m%MOD)%MOD;
ret[i]=(ret[i]+1ll*(ll)(B[i].a+0.5)%MOD)%MOD;
ret[i]=(ret[i]+MOD)%MOD;
}
}
int c[MAX],d[MAX];
void Inv(int *a,int *b,int len)
{
if(len==1){b[0]=fpow(a[0],MOD-2);return;}
Inv(a,b,len>>1);
Multi(a,b,len,c);
Multi(c,b,len,d);
for(int i=0;i<len;++i)b[i]=(b[i]+b[i])%MOD;
for(int i=0;i<len;++i)b[i]=(b[i]+MOD-d[i])%MOD;
}
int n,a[MAX],b[MAX];
int main()
{
while(n=read())
{
for(int i=1;i<=n;++i)a[i]=read()%MOD;
for(int i=1;i<=n;++i)a[i]=(MOD-a[i])%MOD;
a[0]++;
int N;for(N=1;N<=n;N<<=1);
Inv(a,b,N);
printf("%d\n",b[n]);
memset(a,0,sizeof(a));memset(b,0,sizeof(b));
}
return 0;
}
很生疏的方法二
这种东西显然也可以\(CDQ\)分治+\(FFT\)来做
简称分治\(FFT\)
怎么考虑?
式子长成这样:
\(f[n]=\sum_{i=0}^na[i]\times f[n-i],f[0]=0\)
一定要求出前面的才能计算后面的。
每次考虑左半段对于右半段的贡献
直接拿左半段和右半段,(要求的东西)做卷积
这样,对于每一项的系数,都是右半段每个点的一部分贡献。累加即可。
复杂度\(O(nlog^2n)\)
模数\(313\)依旧蛋疼。
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<set>
#include<map>
#include<vector>
#include<queue>
using namespace std;
#define ll long long
#define ull unsigned long long
#define RG register
#define MAX 288888
#define MOD (313)
const double Pi=acos(-1);
const int m=sqrt(MOD);
inline int read()
{
RG int x=0,t=1;RG char ch=getchar();
while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
if(ch=='-')t=-1,ch=getchar();
while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
return x*t;
}
int fpow(int a,int b){int s=1;while(b){if(b&1)s=1ll*s*a%MOD;a=1ll*a*a%MOD;b>>=1;}return s;}
struct Complex{double a,b;}W[MAX],A[MAX],B[MAX],C[MAX],D[MAX];
Complex operator+(Complex a,Complex b){return (Complex){a.a+b.a,a.b+b.b};}
Complex operator-(Complex a,Complex b){return (Complex){a.a-b.a,a.b-b.b};}
Complex operator*(Complex a,Complex b){return (Complex){a.a*b.a-a.b*b.b,a.a*b.b+a.b*b.a};}
int r[MAX];
void FFT(Complex *P,int N,int opt)
{
for(int i=0;i<N;++i)if(i<r[i])swap(P[i],P[r[i]]);
for(int i=1;i<N;i<<=1)
for(int p=i<<1,j=0;j<N;j+=p)
for(int k=0;k<i;++k)
{
Complex w=(Complex){W[N/i*k].a,W[N/i*k].b*opt};
Complex X=P[j+k],Y=P[i+j+k]*w;
P[j+k]=X+Y;P[i+j+k]=X-Y;
}
if(opt==-1)for(int i=0;i<N;++i)P[i].a/=1.0*N;
}
void Multi(int *a,int *b,int len,int *ret)
{
for(int i=0;i<(len<<1);++i)A[i]=B[i]=C[i]=D[i]=(Complex){0,0};
for(int i=0;i<len;++i)
{
a[i]%=MOD;b[i]%=MOD;
A[i]=(Complex){(a[i]/m)*1.0,0};
B[i]=(Complex){(a[i]%m)*1.0,0};
C[i]=(Complex){(b[i]/m)*1.0,0};
D[i]=(Complex){(b[i]%m)*1.0,0};
}
int N,l=0;
for(N=1;N<=len;N<<=1)++l;
for(int i=0;i<N;++i)r[i]=(r[i>>1]>>1)|((i&1)<<(l-1));
for(int i=1;i<N;i<<=1)
for(int k=0;k<i;++k)W[N/i*k]=(Complex){cos(k*Pi/i),sin(k*Pi/i)};
FFT(A,N,1);FFT(B,N,1);FFT(C,N,1);FFT(D,N,1);
for(int i=0;i<N;++i)
{
Complex tmp=A[i]*C[i];
C[i]=B[i]*C[i],B[i]=B[i]*D[i],D[i]=D[i]*A[i];
A[i]=tmp;C[i]=C[i]+D[i];
}
FFT(A,N,-1);FFT(B,N,-1);FFT(C,N,-1);
for(int i=0;i<len;++i)
{
ret[i]=0;
ret[i]=(ret[i]+1ll*(ll)(A[i].a+0.5)%MOD*m%MOD*m%MOD)%MOD;
ret[i]=(ret[i]+1ll*(ll)(C[i].a+0.5)%MOD*m%MOD)%MOD;
ret[i]=(ret[i]+1ll*(ll)(B[i].a+0.5)%MOD)%MOD;
ret[i]=(ret[i]+MOD)%MOD;
}
}
int n,a[MAX],x[MAX],y[MAX],f[MAX];
void CDQ(int l,int r)
{
if(l==r){f[l]=(f[l]+a[l])%MOD;return;}
int mid=(l+r)>>1,N;
CDQ(l,mid);for(N=1;N<=(r-l+1);N<<=1);
for(int i=0;i<=N;++i)x[i]=y[i]=0;
for(int i=l;i<=mid;++i)x[i-l]=f[i];
for(int i=0;i<=r-l;++i)y[i]=a[i];
Multi(x,y,N,x);
for(int i=mid+1;i<=r;++i)f[i]=(f[i]+x[i-l])%MOD;
CDQ(mid+1,r);
}
int main()
{
while(n=read())
{
for(int i=1;i<=n;++i)a[i]=read()%MOD;
int N;for(N=1;N<=n;N<<=1);
CDQ(1,n);
printf("%d\n",f[n]);
memset(f,0,sizeof(f));
memset(a,0,sizeof(a));
}
return 0;
}
【HDU5730】Shell Necklace(多项式运算,分治FFT)的更多相关文章
- HDU - 5730 :Shell Necklace(CDQ分治+FFT)
Perhaps the sea‘s definition of a shell is the pearl. However, in my view, a shell necklace with n b ...
- HDU 5730 Shell Necklace(CDQ分治+FFT)
[题目链接] http://acm.hdu.edu.cn/showproblem.php?pid=5730 [题目大意] 给出一个数组w,表示不同长度的字段的权值,比如w[3]=5表示如果字段长度为3 ...
- #8 //HDU 5730 Shell Necklace(CDQ分治+FFT)
Description 给出长度分别为1~n的珠子,长度为i的珠子有a[i]种,每种珠子有无限个,问用这些珠子串成长度为n的链有多少种方案 题解: dp[i]表示组合成包含i个贝壳的项链的总方案数 转 ...
- HDU5730 Shell Necklace(DP + CDQ分治 + FFT)
题目 Source http://acm.hdu.edu.cn/showproblem.php?pid=5730 Description Perhaps the sea‘s definition of ...
- hdu5730 Shell Necklace 【分治fft】
题目 简述: 有一段长度为n的贝壳,将其划分为若干段,给出划分为每种长度的方案数,问有多少种划分方案 题解 设\(f[i]\)表示长度为\(i\)时的方案数 不难得dp方程: \[f[i] = \su ...
- hdu 5730 Shell Necklace——多项式求逆+拆系数FFT
题目:http://acm.hdu.edu.cn/showproblem.php?pid=5730 可以用分治FFT.但自己只写了多项式求逆. 和COGS2259几乎很像.设A(x),指数是长度,系数 ...
- [题解] BZOJ 3456 洛谷 P4841 [集训队作业2013]城市规划 多项式,分治FFT
题目 令\(f_i\)表示n个点的答案.考虑容斥,用所有连边方案减去有多个连通块的方案.枚举1号点所在的连通块大小: \(f_i=2^{i(i-1)/2}-\sum_{j>0}^{i-1}f_j ...
- hdu5730 Shell Necklace
重温了这道cdq+FFT 讲白了就是不断对 dp[l~mid] 和 sh[1~r] 进行fft 得到 dp[mid+1~r] #include<bits/stdc++.h> using n ...
- [bzoj3625][Codeforces 250 E]The Child and Binary Tree(生成函数+多项式运算+FFT)
3625: [Codeforces Round #250]小朋友和二叉树 Time Limit: 40 Sec Memory Limit: 256 MBSubmit: 650 Solved: 28 ...
- 【HDU5730】 Shell Necklace
HDU5730 Shell Necklace 题目大意 已知连续i(1<=i<=n)个贝壳组合成一段项链的方案数a[i],求组合成包含n个贝壳的项链的总方案数. Solution cdq分 ...
随机推荐
- 深入解析QML引擎, 第1部分:QML文件加载
译者注:这个解析QML引擎的文章共4篇,分析非常透彻,在国内几乎没有找到类似的分析,为了便于国内的QT/QML爱好者和工作者也能更好的学习和理解QML引擎,故将这个系列的4篇文章翻译过来.翻译并不是完 ...
- ----------BMI指数小程序----------
# 1.创建并输出菜单, 菜单是不可变的. 所以使用元组# menus = ("1, 录入", "2, 查询", "3, 删除", &quo ...
- 「Leetcode」975. Odd Even Jump(Java)
分析 注意到跳跃的方向是一致的,所以我们需要维护一个数接下来跳到哪里去的问题.换句话说,就是对于一个数\(A_i\),比它大的最小值\(A_j\)是谁?或者反过来. 这里有两种方案,一种是单调栈,简单 ...
- 区块链技术:每位CEO都应了解
区块链技术有可能成为一项广泛应用的突破性技术,像蒸汽机.电力或因特网那 样,改变整个社会和经济的运行方式. 对企业而言,信任至关重要.今天,我们基于信任,将钱存放在银行,通过电商企业 网购产品,并且依 ...
- 人脸辨识,用树莓派Raspberry Pi实现舵机云台追踪脸孔
影像辨识作为近年最热门的专业技术之一,广泛用于智慧监视器.车电监控.智慧工厂.生物医疗电子等等:其中,人脸辨识是一个很重要的部分,网络上已经有相当多的资源可供下载使用:于是我们使用舵机云台作为镜头旋转 ...
- 深度学习论文笔记:Deep Residual Networks with Dynamically Weighted Wavelet Coefficients for Fault Diagnosis of Planetary Gearboxes
这篇文章将深度学习算法应用于机械故障诊断,采用了“小波包分解+深度残差网络(ResNet)”的思路,将机械振动信号按照故障类型进行分类. 文章的核心创新点:复杂旋转机械系统的振动信号包含着很多不同频率 ...
- loadrunner socket协议问题归纳(5)
获取服务器的返回值,可以用web_reg_save_param函数,该参数最好放到: 语法: int web_reg_save_param(const char *ParamName, <lis ...
- Table Tennis Game 2(找规律)
Description Misha and Vanya have played several table tennis sets. Each set consists of several serv ...
- Alpha发布——视频博客
1.视频链接 视频上传至优酷自频道,地址链接:https://v.youku.com/v_show/id_XMzg5MzQ4MzM2MA==.html?spm=a2h0k.11417342.sores ...
- 【每日scrum】NO.8
(1) 在图的设计过程中掌握了图的基本运算函数的算法的理解和程序的有效吸收,包括图的深度和广度优先的遍历,对图的联通分量的求解,图的最小生成树,图的拓扑排序,图的关键路径, (2)在迪杰斯特拉算法的基 ...