题目大意:用$[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+快速幂的更多相关文章

  1. codeforces E. Okabe and El Psy Kongroo(dp+矩阵快速幂)

    题目链接:http://codeforces.com/contest/821/problem/E 题意:我们现在位于(0,0)处,目标是走到(K,0)处.每一次我们都可以从(x,y)走到(x+1,y- ...

  2. Codeforces 621E Wet Shark and Block【dp + 矩阵快速幂】

    题意: 有b个blocks,每个blocks都有n个相同的0~9的数字,如果从第一个block选1,从第二个block选2,那么就构成12,问对于给定的n,b有多少种构成方案使最后模x的余数为k. 分 ...

  3. 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 ...

  4. HDU 5434 Peace small elephant 状压dp+矩阵快速幂

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5434 Peace small elephant  Accepts: 38  Submissions: ...

  5. 【BZOJ】2004: [Hnoi2010]Bus 公交线路 状压DP+矩阵快速幂

    [题意]n个点等距排列在长度为n-1的直线上,初始点1~k都有一辆公车,每辆公车都需要一些停靠点,每个点至多只能被一辆公车停靠,且每辆公车相邻两个停靠点的距离至多为p,所有公车最后会停在n-k+1~n ...

  6. 【BZOJ】4861: [Beijing2017]魔法咒语 AC自动机+DP+矩阵快速幂

    [题意]给定n个原串和m个禁忌串,要求用原串集合能拼出的不含禁忌串且长度为L的串的数量.(60%)n,m<=50,L<=100.(40%)原串长度为1或2,L<=10^18. [算法 ...

  7. BZOJ5298 CQOI2018 交错序列 【DP+矩阵快速幂优化】*

    BZOJ5298 CQOI2018 交错序列 [DP+矩阵快速幂优化] Description 我们称一个仅由0.1构成的序列为"交错序列",当且仅当序列中没有相邻的1(可以有相邻 ...

  8. CodeForces 185A. Plant (矩阵快速幂)

    CodeForces 185A. Plant (矩阵快速幂) 题意分析 求解N年后,向上的三角形和向下的三角形的个数分别是多少.如图所示: N=0时只有一个向上的三角形,N=1时有3个向上的三角形,1 ...

  9. BZOJ 3160: 万径人踪灭 FFT+快速幂+manacher

    BZOJ 3160: 万径人踪灭 题目传送门 [题目大意] 给定一个长度为n的01串,求有多少个回文子序列? 回文子序列是指从原串中找出任意个,使得构成一个回文串,并且位置也是沿某一对称轴对称. 假如 ...

随机推荐

  1. nginx怎么与tomcat完美结合

    nginx怎么与tomcat完美结合 现在公司一个服务器上需要部署两个项目,其中一个项目已经正式上线,并且已经占用了80端口,另外一个项目 部署上去后,访问必须要加端口号,这样的用户体验非常不好,那么 ...

  2. 一款非常好用的boostrap的验证插件、再也不用自己手写正则表达式和js了

    基于jquery.bootstrap数据验证插件bootstrapValidator教程 bootstrap:能够增加兼容性的强大框架. 因为项目需要数据验证,看bootstrapValidator ...

  3. 2018.09.25 poj2068 Nim(博弈论+dp)

    传送门 题意简述:m个石子,有两个队每队n个人循环取,每个人每次取石子有数量限制,取最后一块的输,问先手能否获胜. 博弈论+dp. 我们令f[i][j]f[i][j]f[i][j]表示当前第i个人取石 ...

  4. 使用async-http-client实现异步批量http请求

    最近项目中需要在微服务中调用rest接口,而且需要调用得次数很多,所以同步得http客户端已经不满足要求,在网上查阅资料后发现了async-http-client这个包得性能不错,所以写了个demo测 ...

  5. MFC框架仿真<三>R T T I

    RTTI,简单的说,就是判定A类是否为B类的基类.将书本的内容最大程度的简化,如下图的类层次,现在解决的问题就是:判定“梨”是否是“红富士”的基类.

  6. MySQL性能调优与架构设计——第 18 章 高可用设计之 MySQL 监控

    第 18 章 高可用设计之 MySQL 监控 前言: 一个经过高可用可扩展设计的 MySQL 数据库集群,如果没有一个足够精细足够强大的监控系统,同样可能会让之前在高可用设计方面所做的努力功亏一篑.一 ...

  7. Delphi for iOS开发指南(4):在iOS应用程序中使用不同风格的Button组件

    http://blog.csdn.net/DelphiTeacher/article/details/8923481 在FireMonkey iOS应用程序中的按钮 FireMoneky定义了不同类型 ...

  8. 拷贝构造函数——防篡改

    对于普通类型的对象来说,他们之间的复制是简单的,比如: int a = 88; int b = a; 而类和普通对象不同,类对象内部结构一般较为复杂,存在各种成员变量. #include <io ...

  9. Android 实现界面(Activity)的跳转

    界面跳转 如,我想重一个界面A跳转到界面B,可以用,setContentView(R.layout.activity_login); 但是他其实只是将改界面铺在了最顶层,而按menu这些菜单其实还是底 ...

  10. Alwayson--问题总结二

    1. 备份首选项作用 答:备份首选项并不影响实际的备份操作,只是在备份前提供标示当前副本是否是推荐的备份副本.管理员可以忽略备份首选项在任意副本上执行完整备份和日志备份. 2. 在辅助副本和主副本备份 ...