原文链接http://www.cnblogs.com/zhouzhendong/p/8848990.html

题目传送门 - CodeForces 623E

题意

  给定$n,k$。

  让你构造序列$a(0<a_i<2^k)$,满足$b_i(b_i=a_1\ or\ a_2\ or\ \cdots\ or\ a_i)$严格单调递增。($or$为按位或)

  问你方案总数。对$10^9+7$取模。

  $n\leq 10^{18},k\leq 30000$

题解

  毛爷爷论文题。

  我怀疑我看到的是假论文。里面不仅题面有点小问题,题解也有大问题。导致我一脸懵逼了好久QAQ。

  做这题时大概是觉得今天效率太低了,就$SKIP$了猜题解过程直接看题解了。

  考虑你有$k$个数位,要保证单调递增,由于是$or$运算,所以值为$1$的数位不管怎样或都不变了,所以每多一个$a_i$至少要多让一个数位变成$1$。

  因为只有$k$个数位,所以$a$的元素个数最多有$n$个,即$n\leq k$。当$n>k$时就是无解,输出$0$。

  现在我们首先考虑大力$DP$。

  设$dp_{i,j}$表示前$i$个数占用了$j$个二进制位的方案数。

  则不难列出转移方程:

$$dp_{i+1,x}=\sum_{j=0}^{x-1}2^j\binom{x}{j}dp_{i,j}$$

  注意$j$从$0$开始枚举其实和从$i$开始是等价的。

  因为原本就有$1$的数位,新增的数的那一位不管是$0$还是$1$都等价,所以要乘$2^j$。

  $\binom{x}{j}$表示把$j$个二进制位$1$插入到新的$x$个二进制位$1$中的方案数。

  但是这样太慢了,要$TLE$。

  我们考虑升级一下上面的那个转移方程。

  设原本有$x$个数,现在一下子加入$y$个数,写出转移方程:

$$dp_{x+y,i}=\sum_{j=0}^{i}2^{jy}\binom{i}{j}dp_{x,j}\cdot dp_{y,i-j}$$

  其中,由于要加入$y$个数字,每一个数字都在原有的$j$个二进制位$1$中贡献了$2^j$的系数(和之前同理),所以总的系数贡献就是$(2^j)^y=2^{jy}$了。

  组合数意义还是和之前一样了。

  我们发现这个是个多项式卷积的形式,所以可以直接$FFT$优化。

  注意这个$FFT$要拆系数,不然要爆$LL$。

  这样的话,我们就不用一次一次转移,可以通过之前得到的结果来一坨一坨转移。

  然后我们发现,我们可以运用倍增快速幂的做法来解决整个运算过程。

  我们要求的是$dp_{n,0\cdots k}$。

  最终的答案就是$\sum_{i=0}^{k}\binom{k}{i}dp_{n,i}$。

  注意,我代码里面把$k$写成了$m$。

  时间复杂度$O(k\log^2 k)$。

  听说有人用$FFT$+多项式求逆+多项式除法……等等算法,复杂度$O(k\log k)$干掉了此题??但是由于大常数却没快多少……

代码

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
LL read(){
LL x=0;
char ch=getchar();
while (!('0'<=ch&&ch<='9'))
ch=getchar();
while ('0'<=ch&&ch<='9')
x=(x<<1)+(x<<3)+ch-48,ch=getchar();
return x;
}
const int N=1<<17;
const LL mod=1e9+7;
double PI=acos(-1.0);
int n,m;
int s,d,R[N];
LL Fac[N],Inv[N];
LL Pow(LL x,LL y){
if (!y)
return 1LL;
LL xx=Pow(x,y/2);
xx=xx*xx%mod;
if (y&1LL)
xx=xx*x%mod;
return xx;
}
struct C{
double r,i;
C(){}
C(double a,double b){r=a,i=b;}
C operator + (C x){return C(r+x.r,i+x.i);}
C operator - (C x){return C(r-x.r,i-x.i);}
C operator * (C x){return C(r*x.r-i*x.i,r*x.i+i*x.r);}
}w[N],A[N],B[N];
LL tot[N],dp[N],now[N],D[N],E[N];
void FFT(C a[],int n){
for (int i=0;i<n;i++)
if (i<R[i])
swap(a[i],a[R[i]]);
for (int t=n>>1,d=1;d<n;d<<=1,t>>=1)
for (int i=0;i<n;i+=(d<<1))
for (int j=0;j<d;j++){
C tmp=w[t*j]*a[i+j+d];
a[i+j+d]=a[i+j]-tmp;
a[i+j]=a[i+j]+tmp;
}
}
void FFT_mul(LL a[],LL b[],LL c[],int n){
for (int i=0;i<n;i++)
c[i]=0,A[i]=C(a[i]>>15,0),B[i]=C(b[i]>>15,0);
FFT(A,n),FFT(B,n);
for (int i=0;i<n;i++)
A[i]=A[i]*B[i],w[i].i*=-1.0;
FFT(A,n);
for (int i=0;i<n;i++){
tot[i]=((LL)(A[i].r/n+0.5))%mod;
c[i]=(c[i]+tot[i]*(1LL<<30))%mod;
w[i].i*=-1.0;
}
for (int i=0;i<n;i++)
A[i]=C(a[i]&32767,0),B[i]=C(b[i]&32767,0);
FFT(A,n),FFT(B,n);
for (int i=0;i<n;i++)
A[i]=A[i]*B[i],w[i].i*=-1.0;
FFT(A,n);
for (int i=0;i<n;i++){
tot[i]=(tot[i]+((LL)(A[i].r/n+0.5)))%mod;
c[i]=(c[i]+((LL)(A[i].r/n+0.5)))%mod;
w[i].i*=-1.0;
}
for (int i=0;i<n;i++){
A[i]=C((a[i]>>15)+(a[i]&32767),0);
B[i]=C((b[i]>>15)+(b[i]&32767),0);
}
FFT(A,n),FFT(B,n);
for (int i=0;i<n;i++)
A[i]=A[i]*B[i],w[i].i*=-1.0;
FFT(A,n);
for (int i=0;i<n;i++){
LL v=((LL)(A[i].r/n+0.5))%mod;
c[i]=(c[i]+(v-tot[i]+mod)%mod*(1LL<<15))%mod;
w[i].i*=-1.0;
}
}
void DP_mul(LL a[],LL b[],LL c[],int &x,int &y){
for (int i=0;i<s;i++)
D[i]=E[i]=0;
for (int i=0;i<=m;i++){
D[i]=a[i]*Inv[i]%mod*Pow(2,1LL*y*i%(mod-1))%mod;
E[i]=b[i]*Inv[i]%mod;
}
FFT_mul(D,E,c,s);
for (int i=0;i<s;i++)
c[i]=c[i]*(i<=m?Fac[i]:0)%mod;
x+=y;
}
void reads(){
LL nn=read();
scanf("%d",&m);
n=(nn>m)?-1:(int)nn;
}
int main(){
reads();
if (n==-1){
puts("0");
return 0;
}
Fac[0]=1;
for (int i=1;i<=m;i++)
Fac[i]=Fac[i-1]*i%mod;
Inv[m]=Pow(Fac[m],mod-2);
for (int i=m-1;i>=0;i--)
Inv[i]=Inv[i+1]*(i+1)%mod;
for (s=1,d=0;s<m*2+2;s<<=1,d++);
for (int i=0;i<s;i++){
R[i]=(R[i>>1]>>1)|((i&1)<<(d-1));
w[i]=C(cos(2*i*PI/s),sin(2*i*PI/s));
}
dp[0]=1;
for (int i=1;i<=m;i++)
now[i]=1;
int x,y;
for (x=0,y=1;y<=n;){
if (n&y)
DP_mul(dp,now,dp,x,y);
DP_mul(now,now,now,y,y);
}
LL ans=0;
for (int i=0;i<=m;i++)
ans=(ans+dp[i]*Fac[m]%mod*Inv[i]%mod*Inv[m-i])%mod;
printf("%I64d",ans);
return 0;
}

  

CodeForces 623E Transforming Sequence 动态规划 倍增 多项式 FFT 组合数学的更多相关文章

  1. BZOJ 5381 or & Codeforces 623E Transforming Sequence DP+NTT

    两道题题意都是一样的 不过$CF$的模数是$10^9+7$ 很简单的分析发现$A_i$项一定要有一个之前没有出现过的二进制位才能满足条件 考虑$DP$来做 设$f_{i,j}$表示$i$个数用了二进制 ...

  2. 【codeforces 623E】 Transforming Sequence

    http://codeforces.com/problemset/problem/623/E (题目链接) 题意 长度为${n}$的满足前缀按位或为单调递增的${k}$位序列.要求每个位置为${[1, ...

  3. 【LOJ#575】【LNR#2】不等关系(容斥,动态规划,分治FFT)

    [LOJ#575][LNR#2]不等关系(容斥,动态规划,分治FFT) 题面 LOJ 题解 一个暴力\(dp\),设\(f[i][j]\)表示考虑完了前\(i\)个位置,其中最后一个数在前面所有数中排 ...

  4. Codeforces 601B. Lipshitz Sequence(单调栈)

    Codeforces 601B. Lipshitz Sequence 题意:,q个询问,每次询问给出l,r,求a数组[l,r]中所有子区间的L值的和. 思路:首先要观察到,斜率最大值只会出现在相邻两点 ...

  5. CodeForces 553E Kyoya and Train 动态规划 多项式 FFT 分治

    原文链接http://www.cnblogs.com/zhouzhendong/p/8847145.html 题目传送门 - CodeForces 553E 题意 一个有$n$个节点$m$条边的有向图 ...

  6. CodeForces 286E Ladies' Shop 多项式 FFT

    原文链接http://www.cnblogs.com/zhouzhendong/p/8781889.html 题目传送门 - CodeForces 286E 题意 首先,给你$n$个数(并告诉你$m$ ...

  7. CodeForces 958F3 Lightsabers (hard) 启发式合并/分治 多项式 FFT

    原文链接http://www.cnblogs.com/zhouzhendong/p/8835443.html 题目传送门 - CodeForces 958F3 题意 有$n$个球,球有$m$种颜色,分 ...

  8. Codeforces 438E. The Child and Binary Tree 多项式,FFT

    原文链接www.cnblogs.com/zhouzhendong/p/CF438E.html 前言 没做过多项式题,来一道入门题试试刀. 题解 设 $a_i$ 表示节点权值和为 $i$ 的二叉树个数, ...

  9. CodeForces 528D Fuzzy Search 多项式 FFT

    原文链接http://www.cnblogs.com/zhouzhendong/p/8782849.html 题目传送门 - CodeForces 528D 题意 给你两个串$A,B(|A|\geq| ...

随机推荐

  1. P1494 [国家集训队]小Z的袜子

    题目 P1494 [国家集训队]小Z的袜子 解析 在区间\([l,r]\)内, 任选两只袜子,有 \[r-l+1\choose2\] \[=\frac{(r-l+1)!}{2!(r-l-1)!}\] ...

  2. 清北学堂Day3

    卷积公式(Dirichlet卷积) 这个式子看上去就很变态,那么他是什么意思呢: 就是说 函数f(x)和g(x)对于n的卷积等于n的每一个因子d在f(x)上的值乘上d/n在g(x)上的值的和 例:设g ...

  3. Spring Cloud Data Flow 中的 ETL

    Spring Cloud Data Flow 中的 ETL 影宸风洛 程序猿DD 今天 来源:SpringForAll社区 1 概述 Spring Cloud Data Flow是一个用于构建实时数据 ...

  4. luoguP4705 玩游戏

    好好玩 即对于k∈[1,t] 求(ax+by)^k 以下图片均来自于: 在Ta的博客查看 一 二项式展开: 设: 那么: 可以卷积了 二 求: (PS:随机序列的0~k次方和,这是一个经典问题.) 我 ...

  5. (最短路 Floyd) P2910 [USACO08OPEN]寻宝之路Clear And Present Danger 洛谷

    题意翻译 题目描述 农夫约翰正驾驶一条小艇在牛勒比海上航行. 海上有N(1≤N≤100)个岛屿,用1到N编号.约翰从1号小岛出发,最后到达N号小岛. 一张藏宝图上说,如果他的路程上经过的小岛依次出现了 ...

  6. Python并发编程之IO模型

    目录 IO模型介绍 阻塞IO(blocking IO) 非阻塞IO(non-blocking IO) IO多路复用 异步IO IO模型比较分析 selectors模块 一.IO模型介绍 Stevens ...

  7. usb驱动程序小结(六)

    title: usb驱动程序小结 tags: linux date: 2018/12/20/ 17:59:51 toc: true --- usb驱动程序小结 linux中为usb驱动也提供了一套总线 ...

  8. wiki中文语料的word2vec模型构建

    一.利用wiki中文语料进行word2vec模型构建 1)数据获取 到wiki官网下载中文语料,下载完成后会得到命名为zhwiki-latest-pages-articles.xml.bz2的文件,里 ...

  9. Linux性能优化实战:到底应该怎样理解平均负载(02)

    一.平均负载与CPU使用率并没有直接关系 1.平均负载 单位时间内,系统处于可运行状态和不可终端状态的平均进程数也就是平均活跃进程数,它和cpu使用率并没有直接关系, 可运行状态: 正在使用的cpu或 ...

  10. kubernetes云平台管理实战: 集群部署(一)

    一.环境规划 1.架构拓扑图 2.主机规划 3.软件版本 [root@k8s-master ~]# cat /etc/redhat-release CentOS Linux release 7.4.1 ...