【codeforces 623E】dp+FFT+快速幂
题目大意:用$[1,2^k-1]$之间的证书构造一个长度为$n$的序列$a_i$,令$b_i=a_1\ or\ a_2\ or\ ...\ or a_i$,问使得b序列严格递增的方案数,答案对$10^9+7$取模。
数据范围,$n≤10^{18}$,$k≤30000$。
考虑用dp来解决这一题,我们用$f[i][j]$来表示前$i$个数中,使用了$j$个二进制位(注意!并不是前$j$个),那么答案显然为$\sum_{i=0}^{k} \binom{n}{i} \times f[n][i]$。
考虑如何用前面求得的数值来更新$f[x+y][i]$,不妨设$j∈[1,i]$。
不难推出,用了$x$个数,在$i$个二进制位中选用了$j$个二进制位的方案数为$\binom{i}{j} \times f[x][j]$。
然后,用掉$y$个数,并选用余下$i-j$个二进制位的方案数为$f[y][i-j]$。
考虑到前面$x$个数已经选择了$j$个二进制位,那么剩下的$y$个数,在这$j$个位置上,均可以随便填0或1,方案数为$(2^j)^y$。
通过上文分析,得$f[x+y][i]=\sum_{j=1}^{i} f[x][j] \times \binom{i}{j} \times f[y][i-j] \times (2^j)^y$。
通过简单整理,$=i!\sum_{j=1}^{i} \frac{f[x][j]\times (2^j)^y}{j!} \times \frac{f[y][i-j]}{(i-j)!}$。
然后,我们就可以通过NTT,进行dp式子的转移。
不过此题的模数非常恶心,所以需要用任意模数FFT。
考虑到$n$范围非常大,所以$x$和$y$的选择必须要有技巧,我们可以用类似快速幂的算法,加速转移,详情可见代码。
时间复杂度为$O(k\ log\ k\ log\ n)$。
#include<bits/stdc++.h>
#define L long long
#define MOD 1000000007
#define H 16
#define M 1<<H
#define hh 32768
#define PI acos(-1)
using namespace std;
int nn;
int k; L n; L pow_mod(L x,L k){
L ans=;
while(k){
if(k&) ans=ans*x%MOD;
k>>=; x=x*x%MOD;
}
return ans;
} struct cp{
double i,r;
cp(){i=r=;}
cp(double rr,double ii){i=ii; r=rr;}
friend cp operator +(cp a,cp b){return cp(a.r+b.r,a.i+b.i);}
friend cp operator -(cp a,cp b){return cp(a.r-b.r,a.i-b.i);}
friend cp operator *(cp a,cp b){return cp(a.r*b.r-a.i*b.i,a.r*b.i+a.i*b.r);}
L D(){L hhh=(r+0.499); return hhh%MOD;}
}; cp w[M][H];
void init(){
for(int i=,j=;j<H;j++,i<<=){
for(int k=;k<i;k++)
w[k][j]=cp(cos(*PI*k/i),sin(*PI*k/i));
}
} void change(cp a[],int n){
for(int i=,j=;i<n-;i++){
if(i<j) swap(a[i],a[j]);
int k=n>>;
while(j>=k) j-=k,k>>=;
j+=k;
}
}
void FFT(cp a[],int n,int on){
change(a,n);
cp wn,u,t;
for(int h=,i=;h<=n;h<<=,i++){
for(int j=;j<n;j+=h){
for(int k=j;k<j+(h>>);k++){
wn=w[k-j][i]; if(on==-) wn.i=-wn.i;
u=a[k]; t=a[k+(h>>)]*wn;
a[k]=u+t; a[k+(h>>)]=u-t;
}
}
}
if(on==-)
for(int i=;i<n;i++) a[i].r=a[i].r/n;
} struct poly{
L a[M];
poly(){memset(a,,sizeof(a));}
friend poly operator *(poly a,poly b){
poly c;
static cp A[M],B[M],C[M],D[M],E[M],F[M],G[M];
memset(A,,sizeof(A)); memset(B,,sizeof(B));
memset(C,,sizeof(C)); memset(D,,sizeof(D));
for(int i=;i<nn;i++) A[i].r=a.a[i]%hh,B[i].r=a.a[i]/hh;
for(int i=;i<nn;i++) C[i].r=b.a[i]%hh,D[i].r=b.a[i]/hh;
FFT(A,nn,); FFT(B,nn,); FFT(C,nn,); FFT(D,nn,);
for(int i=;i<nn;i++){
E[i]=A[i]*C[i];
F[i]=A[i]*D[i]+B[i]*C[i];
G[i]=B[i]*D[i];
}
FFT(E,nn,-); FFT(F,nn,-); FFT(G,nn,-);
for(int i=;i<nn;i++)
c.a[i]=(E[i].D()+F[i].D()*hh%MOD+G[i].D()*hh%MOD*hh%MOD)%MOD;
for(int i=k+;i<nn;i++) c.a[i]=;
return c;
}
};
L fac[M]={},invfac[M]={};
L C(int n,int m){return fac[n]*invfac[m]%MOD*invfac[n-m]%MOD;}
poly ans,f,f1,f2;
int main(){
init();
cin>>n>>k; n--;
fac[]=; for(int i=;i<=k;i++) fac[i]=fac[i-]*i%MOD;
invfac[k]=pow_mod(fac[k],MOD-);
for(int i=k-;~i;i--) invfac[i]=invfac[i+]*(i+)%MOD;
for(nn=;nn<=(k*);nn<<=);
L now=;
for(int i=;i<=k;i++) f.a[i]=;
ans=f;
while(n){
if(n&){
f1=ans; f2=f;
for(int i=;i<=k;i++)
f1.a[i]=f1.a[i]*invfac[i]%MOD*pow_mod(pow_mod(,i),now)%MOD;
for(int i=;i<=k;i++)
f2.a[i]=f2.a[i]*invfac[i]%MOD;
ans=f1*f2;
for(int i=;i<=k;i++)
ans.a[i]=ans.a[i]*fac[i]%MOD;
}
f1=f; f2=f;
for(int i=;i<=k;i++)
f1.a[i]=f1.a[i]*invfac[i]%MOD*pow_mod(pow_mod(,i),now)%MOD;
for(int i=;i<=k;i++)
f2.a[i]=f2.a[i]*invfac[i]%MOD;
f=f1*f2;
for(int i=;i<=k;i++)
f.a[i]=f.a[i]*fac[i]%MOD;
n>>=; now<<=;
}
L sum=;
for(int i=;i<=k;i++)
sum=(sum+ans.a[i]*C(k,i))%MOD;
cout<<sum<<endl;
}
【codeforces 623E】dp+FFT+快速幂的更多相关文章
- codeforces E. Okabe and El Psy Kongroo(dp+矩阵快速幂)
题目链接:http://codeforces.com/contest/821/problem/E 题意:我们现在位于(0,0)处,目标是走到(K,0)处.每一次我们都可以从(x,y)走到(x+1,y- ...
- Codeforces 621E Wet Shark and Block【dp + 矩阵快速幂】
题意: 有b个blocks,每个blocks都有n个相同的0~9的数字,如果从第一个block选1,从第二个block选2,那么就构成12,问对于给定的n,b有多少种构成方案使最后模x的余数为k. 分 ...
- bnuoj 34985 Elegant String DP+矩阵快速幂
题目链接:http://acm.bnu.edu.cn/bnuoj/problem_show.php?pid=34985 We define a kind of strings as elegant s ...
- HDU 5434 Peace small elephant 状压dp+矩阵快速幂
题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5434 Peace small elephant Accepts: 38 Submissions: ...
- 【BZOJ】2004: [Hnoi2010]Bus 公交线路 状压DP+矩阵快速幂
[题意]n个点等距排列在长度为n-1的直线上,初始点1~k都有一辆公车,每辆公车都需要一些停靠点,每个点至多只能被一辆公车停靠,且每辆公车相邻两个停靠点的距离至多为p,所有公车最后会停在n-k+1~n ...
- 【BZOJ】4861: [Beijing2017]魔法咒语 AC自动机+DP+矩阵快速幂
[题意]给定n个原串和m个禁忌串,要求用原串集合能拼出的不含禁忌串且长度为L的串的数量.(60%)n,m<=50,L<=100.(40%)原串长度为1或2,L<=10^18. [算法 ...
- BZOJ5298 CQOI2018 交错序列 【DP+矩阵快速幂优化】*
BZOJ5298 CQOI2018 交错序列 [DP+矩阵快速幂优化] Description 我们称一个仅由0.1构成的序列为"交错序列",当且仅当序列中没有相邻的1(可以有相邻 ...
- CodeForces 185A. Plant (矩阵快速幂)
CodeForces 185A. Plant (矩阵快速幂) 题意分析 求解N年后,向上的三角形和向下的三角形的个数分别是多少.如图所示: N=0时只有一个向上的三角形,N=1时有3个向上的三角形,1 ...
- BZOJ 3160: 万径人踪灭 FFT+快速幂+manacher
BZOJ 3160: 万径人踪灭 题目传送门 [题目大意] 给定一个长度为n的01串,求有多少个回文子序列? 回文子序列是指从原串中找出任意个,使得构成一个回文串,并且位置也是沿某一对称轴对称. 假如 ...
随机推荐
- 选择排序(直接排序)java语言实现
class demo { public static void main(String[] args) { int[] arr={1,4,2,6,8,9,0,5,3,2,2,4,4,6,7,8}; f ...
- LA 4670 Dominating Patterns (AC自动机)
题意:给定n个字符串和一个文本串,查找哪个字符串出现的次数的最多. 析:一匹配多,很明显是AC自动机.只需要对原来的进行修改一下,就可以得到这个题的答案, 计算过程中,要更新次数,并且要映射字符串.如 ...
- webuploader 文件上传总结
$(function() { /** * 初始化Web Uploader */ var uploader = WebUploader.create({ swf : '../mobile/Uploade ...
- Android+PHP开发最佳实践
本书以一个完整的微博应用项目实例为主线,由浅入深地讲解了Android客户端开发和PHP服务端开发的思路和技巧.从前期的产品设计.架构设计,到客户端和服务器的编码实现,再到性能测试和系统优化,以及最后 ...
- Servlet从浅入深
Servlet是什么 servlet 是运行在 Web 服务器中的小型 Java 程序(即:服务器端的小应用程序). servlet 通常通过 HTTP(超文本传输协议)接收和响应来自 Web 客户端 ...
- Linux 系统中进程5中常见状态
运行.中断.不可终端.僵死.停止 R(运行):正在运行 or 在运行队列中等待: S(中断):处于休眠中,等待接收信号,并脱离改状态: D(不可中断):不响应信号输入,即使kill也不起作用: Z(僵 ...
- 理解ValueStack的基本机制 OGNL表达式
ValueStack基础:OGNL(Object Graphic Navigatino Language) OGNL是Struts2中使用的一种表达式语言. 它可以用于,在JSP页面,使用标签方便的访 ...
- Java web 调试技巧之查看浏览器中调试中的network
在java web开发过程中尤其后台开发经常需要查看浏览器调试中的network项:今天在开发在线预览系统时用到了flexpaper插件,这个插件会调用FlexPaperViewer.swf这个软件( ...
- CAS实战の遇到的问题
1.客户端启动报错,报错信息如下: 严重: Exception starting filter CAS Single Sign Out Filter java.lang.IllegalArgument ...
- SYS远程连接出错ORA-01031:Insufficient privileges
http://blog.sina.com.cn/s/blog_5f266ec50100m052.html SYS远程连接出错ORA-01031:Insufficient privileges. 现象: ...