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做法,正难则反,考虑所有情况减去不连通的情况: 而不连通的情况就是那个经典 ...
随机推荐
- Swift学习笔记 - 位移枚举的按位或运算
在OC里面我们经常遇到一些枚举值可以多选的,需要用或运算来把这些枚举值链接起来,这样的我们称为位移枚举,但是在swift里面却不能这么做,下面来讲解一下如何在swift里面使用 OC的位移枚举的区分 ...
- Mybatis plus 高级
最近项目重构 dao层使用的Mybatis plus,有必要总结下. Mybatis plus 会自动维护Mybatis 以及 MyBatis-Spring 相关依赖 所以在构建项目时候 只需要引入 ...
- var与this定义变量的区别以及疑惑
我们知道: var可以定义一个局部变量,当然如果var定义在最外层的话,就是全局的局部变量,也就算是全局变量了. 而this关键字定义的变量准确的说应该算是成员变量.即定义的是调用对象的成员变量. 另 ...
- Activity启动的四种方式
Activity启动方式有四种,分别是: standardsingleTopsingleTasksingleInstance 可以根据实际的需求为Activity设置对应的启动模式,从而可以避免创建大 ...
- PHP 开发环境搭建
1. PHP (1) download PHP and extra the zip file to the folder “C:\tools\php” (2) add the path “;C:\to ...
- Remove Duplicates from Sorted List ,除去链表中相邻的重复元素
Remove Duplicates from Sorted List : Given a sorted linked list, delete all duplicates such that eac ...
- 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 ...
- python作业大纲分析
2018-11-22 目前自学python这么久,零零散散的写了几次作业,下面是几个在完成过程中遇到困难较多的作业. 1.ATM+购物车系统 需求: 1.额度 15000或自定义 2.实现购物商城, ...
- 关于mongodb删除集合后磁盘空间不释放的问题
mongodb删除集合后磁盘空间不释放,只有用db.repairDatabase()去修复才能释放. 但是在修复的过程中如果出现了非正常的mongodb的挂掉,再次启动时启动不了的,需要先修复才可以, ...
- spring3: 对JDBC的支持 之 关系数据库操作对象化
7.3.1 概述 所谓关系数据库对象化其实就是用面向对象方式表示关系数据库操作,从而可以复用. Spring JDBC框架将数据库操作封装为一个RdbmsOperation,该对象是线程安全的.可复 ...