hdu 5730 Shell Necklace——多项式求逆+拆系数FFT
题目:http://acm.hdu.edu.cn/showproblem.php?pid=5730
可以用分治FFT。但自己只写了多项式求逆。
和COGS2259几乎很像。设A(x),指数是长度,系数是方案。 \( A(x)^{k} \) 的 m 次项系数表示 k 个连续段组成长度为 m 的序列的方案数。
\( B(x)=1+F(x)+F^{2}(x)+F^{3}(x)+... \)
\( B(x) = \frac{1}{1-F(x)} \)(通过计算B(x)的逆来看出这个式子)
然后多项式求逆就行了。
注意模数 \( 313=2^{3}*3*13 \) ,原根是10,但那个 23 太小了!如果 len 大于3的话就会除出小数,所以不能直接用NTT!
那么就用FFT。FFT不能中途取模,所以最大的值是 312×312×10000=9734400000,会让FFT的精度变得很低。所以用拆系数FFT。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define db double
#define ll long long
using namespace std;
const int N=1e5+,M=(<<)+,mod=;
const db pi=acos(-);
int n,a[M],b[M],tp[M],len,r[M],base;
struct cpl{db x,y;}A[M],B[M],Ta[M],Tb[M],Tc[M],Td[M],Ini,I;
cpl operator+ (cpl a,cpl b){return (cpl){a.x+b.x,a.y+b.y};}
cpl operator- (cpl a,cpl b){return (cpl){a.x-b.x,a.y-b.y};}
cpl operator* (cpl a,cpl b){return (cpl){a.x*b.x-a.y*b.y,a.x*b.y+a.y*b.x};}
cpl cnj(cpl a){return (cpl){a.x,-a.y};}
int rdn()
{
int ret=;bool fx=;char ch=getchar();
while(ch>''||ch<''){if(ch=='-')fx=;ch=getchar();}
while(ch>=''&&ch<='') ret=ret*+ch-'',ch=getchar();
return fx?ret:-ret;
}
void upd(int &x){x>=mod?x-=mod:;}
int pw(int x,int k)
{int ret=;while(k){if(k&)ret=(ll)ret*x%mod;x=(ll)x*x%mod;k>>=;}return ret;}
void fft(cpl *a,bool fx)
{
for(int i=;i<len;i++)
if(i<r[i])swap(a[i],a[r[i]]);
for(int R=;R<=len;R<<=)
{
int m=R>>;
cpl wn=(cpl){ cos(pi/m),fx?-sin(pi/m):sin(pi/m) };
for(int i=;i<len;i+=R)
{
cpl w=I;
for(int j=;j<m;j++,w=w*wn)
{
cpl x=a[i+j], y=w*a[i+m+j];
a[i+j]=x+y; a[i+m+j]=x-y;
}
}
}
if(!fx)return;
for(int i=;i<len;i++)a[i].x/=len,a[i].y/=len;
}
void mtt(int n,int *a,int *b,int *c)
{
for(len=;len<n<<;len<<=);
for(int i=;i<len;i++)r[i]=(r[i>>]>>)+((i&)?len>>:);
for(int i=;i<n;i++)A[i]=(cpl){ a[i]/base,a[i]%base }; for(int i=n;i<len;i++)A[i]=Ini;
for(int i=;i<n;i++)B[i]=(cpl){ b[i]/base,b[i]%base }; for(int i=n;i<len;i++)B[i]=Ini;
fft(A,); fft(B,);
cpl ta,tb,tc,td;
A[len]=A[]; B[len]=B[];
for(int i=,j=len;i<len;i++,j--)
{
ta=(A[i]+cnj(A[j]))*(cpl){0.5,};
tb=(A[i]-cnj(A[j]))*(cpl){,-0.5};
tc=(B[i]+cnj(B[j]))*(cpl){0.5,};
td=(B[i]-cnj(B[j]))*(cpl){,-0.5};
Ta[i]=ta*tc; Tb[i]=ta*td; Tc[i]=tb*tc; Td[i]=tb*td;
}
A[len]=B[len]=Ini;
for(int i=;i<len;i++)A[i]=Ta[i]+Tb[i]*(cpl){,};
for(int i=;i<len;i++)B[i]=Tc[i]+Td[i]*(cpl){,};
fft(A,); fft(B,);
for(int i=,Da,Db,Dc,Dd;i<n;i++)
{
Da=(ll)(A[i].x+0.5)%mod; Db=(ll)(A[i].y+0.5)%mod;
Dc=(ll)(B[i].x+0.5)%mod; Dd=(ll)(B[i].y+0.5)%mod;
c[i]=(Da*base*base+(Db+Dc)*base+Dd)%mod+mod; upd(c[i]);
}
}
void getinv(int n,int *a,int *b)
{
if(n==){b[]=pw(a[],mod-);return;}
getinv(n+>>,a,b);
mtt(n,a,b,tp);
mtt(n,tp,b,tp);
for(int i=;i<n;i++)b[i]=((b[i]<<)-tp[i])%mod+mod,upd(b[i]);
}
int main()
{
base=sqrt(mod); I.x=;
while()
{
memset(a,,sizeof a);memset(b,,sizeof b);
n=rdn(); if(!n)return ;
for(int i=;i<=n;i++)a[i]=rdn();
for(int i=;i<=n;i++)a[i]=mod-a[i]%mod,upd(a[i]);
a[]++;
getinv(n+,a,b);
printf("%d\n",b[n]);
}
return ;
}
hdu 5730 Shell Necklace——多项式求逆+拆系数FFT的更多相关文章
- hdu 5730 Shell Necklace [分治fft | 多项式求逆]
hdu 5730 Shell Necklace 题意:求递推式\(f_n = \sum_{i=1}^n a_i f_{n-i}\),模313 多么优秀的模板题 可以用分治fft,也可以多项式求逆 分治 ...
- HDU 5730 Shell Necklace(CDQ分治+FFT)
[题目链接] http://acm.hdu.edu.cn/showproblem.php?pid=5730 [题目大意] 给出一个数组w,表示不同长度的字段的权值,比如w[3]=5表示如果字段长度为3 ...
- HDU.5730.Shell Necklace(分治FFT)
题目链接 \(Description\) 有\(n\)个长度分别为\(1,2,\ldots,n\)的珠子串,每个有\(a_i\)种,每种个数不限.求有多少种方法组成长度为\(n\)的串.答案对\(31 ...
- hdu 5730 Shell Necklace —— 分治FFT
题目:http://acm.hdu.edu.cn/showproblem.php?pid=5730 DP式:\( f[i] = \sum\limits_{j=1}^{i} f[i-j] * a[j] ...
- HDU 5730 - Shell Necklace
题意: 给出连续的1-n个珠子的涂色方法 a[i](1<=i<=n), 问长度为n的珠链共有多少种涂色方案 分析: 可以得到DP方程: DP[n] = ∑(i=1,n) (DP[n-i]* ...
- hdu 5730 Shell Necklace fft+cdq分治
题目链接 dp[n] = sigma(a[i]*dp[n-i]), 给出a1.....an, 求dp[n]. n为1e5. 这个式子的形式显然是一个卷积, 所以可以用fft来优化一下, 但是这样也是会 ...
- HDU 5730 Shell Necklace cdq分治+FFT
题意:一段长为 i 的项链有 a[i] 种装饰方式,问长度为n的相连共有多少种装饰方式 分析:采用dp做法,dp[i]=∑dp[j]*a[i-j]+a[i],(1<=j<=i-1) 然后对 ...
- #8 //HDU 5730 Shell Necklace(CDQ分治+FFT)
Description 给出长度分别为1~n的珠子,长度为i的珠子有a[i]种,每种珠子有无限个,问用这些珠子串成长度为n的链有多少种方案 题解: dp[i]表示组合成包含i个贝壳的项链的总方案数 转 ...
- bzoj 3456 城市规划 —— 分治FFT / 多项式求逆 / 指数型生成函数(多项式求ln)
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3456 首先考虑DP做法,正难则反,考虑所有情况减去不连通的情况: 而不连通的情况就是那个经典 ...
随机推荐
- Gentoo系统安装步骤详解
下载镜像 一般我都是用国内的镜像源,不管是centos,ubuntu还是gentoo在国内的镜像来说肯定比国外快 #下载地址mirrors.163.com/gentoo/#我用的x86的http:// ...
- centos、linux关机与重启命令详解
Linux centos关机与重启命令详解与实战 Linux centos重启命令: 1.reboot 2.shutdown -r now 立刻重启(root用户使用) 3.shutdown -r 1 ...
- sem学习
关键字的选取搜索引擎营销的关键字选取是非常重要的一步,合适的关键字可以为企业带来可观的咨询量.关键字一般分4种,品牌词,产品词,行业词,竞品词,对于这四类词不同的推广策略有着不同的侧重点,根据市场情况 ...
- 使用MyCat分表分库原理分析
Mycat可以实现 读写分离 分表分库 主从复制是MySQL自带的哈~ 关于分片取模算法: 根据id进行取模 根据数据库集群的数量(或者说是表数量,mycat里面一个表对应一个库) 使用MyCat ...
- nginx 403错误
1.出现此种错误的原因有可能是所有者对目录没有写的权限,此时可用chmod 777 目录名 先完全放开权限,如果问题解决,则在慢慢缩小访问权限. 解决办法:chown -R nginx_user:ng ...
- Javascript -- 示例:多选下拉选框
1. 示例:多选下拉选框 <html> <head> <meta http-equiv="Content-Type" content="te ...
- scala学习手记7 - 运算符重载
从语法上来说scala是没有运算符的.之前的一节里也曾提到过scala的运算符实际上是方法名,如1 + 2实际上就是1.+(2).我们可以将之视为运算符,是因为scala的一个特性:如果方法的参数小于 ...
- virtio guest side implementation: PCI, virtio device, virtio net and virtqueue
With the publishing of OASIS virtio specification version 1.0, virtio made another big step in becom ...
- C++ 进阶学习 ——模板
模板和重载类似,比重载更省事 通常有两种形式:函数模板和类模板: 函数模板针对仅参数类型不同的函数: 类模板针对仅数据成员和成员函数类型不同的类. 一个简单的函数模板 template <cla ...
- CentOS下安装mysql及配置使用
最近一直使用的是CentOS,平时用的最多的数据库是Sql Server,对于mysql还停留在上学的时候,早已忘得一干二净,写这篇内容目的是,重新学习如何安装使用mysql. 一.安装mysql 操 ...