http://codeforces.com/problemset/problem/623/E (题目链接)

题意

  长度为${n}$的满足前缀按位或为单调递增的${k}$位序列。要求每个位置为${[1,2^k-1]}$之间的整数,求方案数。

Solution

  毛爷爷论文题,然而论文上的${dp}$方程都是错的,坑爹啊!!

  首先,每个数的二进制位上一定存在一位为${1}$,且之前的数的这一位上都为${0}$,这样才能保证按位或的前缀和单调递增。那么当${n>k}$时,显然答案是等于${0}$的,所以我们只讨论${n<=k}$同级的情况。

  ${f_{i,j}}$表示已经放了前${i}$个数,占用了二进制位中的${j}$位。那么我们考虑转出,则${f_{i+1,j+l}}$得到的${f_{i,j}}$的贡献就是:${f_{i,j}*2^j*C_{k-j}^{l}}$。${2^j}$指的是新添加的一个数在之前已经被占用的${j}$位上,可以随意取${0}$或${1}$。

  考虑优化,如果对于所有的${0<=i<=k}$,我们知道了${f_{x,i}}$和${f_{y,i}}$,我们可以直接求出${f_{x+y},i}$的值:$${f_{x+y,i}=\sum_{j=0}^{i}  {f_{x,j}*2^{yj}*f_{y,i-j}*\frac{C_{k-j}^{i-j}}{C_{k}^{i-j}} }  }$$

  其中,${f_{x,j}}$表示前${x}$个数的选择方案,$2^{yj}$表示后$y$个数中,已经被前$x$个数占据的$j$位可以任意填$0$或$1$。因为${f_{y,i-j}}$中的${i-j}$位是在所有位数${k}$位中选取的,可能就会与之前选取的${x}$个数占用的${j}$位有重叠,而这是不兹瓷的,所以这${i-j}$位只能在剩下的${k-j}$位中选了。我们化简这个式子,得到:$${k!*(k-i)!*f_{x+y,i}=\sum_{j=0}^{i} { [f_{x,j}*2^{yj}*(k-j)!]*[ f_{y,i-j}*(k-(i-j))! ]  }  }$$

  于是等式右边的式子我们可以${FFT}$求出,用类似于快速幂的思想,依次求出${1,2,4,8,16······}$然后看${n}$的当前二进制位上是否为${1}$,如果是${1}$就给答案卷积上这一位的值。复杂度${O(klog^2k)}$

细节

  注意${FFT}$精度感人,我们需要预处理${w_n^k}$。

代码

// codeforces 623E
#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<complex>
#include<cstdio>
#include<cmath>
#include<queue>
#define LL long long
#define inf 1ll<<60
#define MOD 1000000007
#define M (1<<15)
#define Pi acos(-1.0)
#define free(a) freopen(a".in","r",stdin),freopen(a".out","w",stdout);
using namespace std; typedef complex<double> E;
const int maxn=100010;
E a[maxn],b[maxn],c[maxn],d[maxn],A[maxn],B[maxn],C[maxn],w[maxn];
LL F[maxn],G[maxn],f[maxn],g[maxn];
LL fac[maxn],ifac[maxn],rev[maxn],K,N,L;
LL n; LL power(LL a,LL b) {
LL res=1;
while (b) {
if (b&1) res=res*a%MOD;
b>>=1;a=a*a%MOD;
}
return res;
}
void DFT(E *t,LL f) {
for (int i=0;i<N;i++) if (rev[i]>i) swap(t[i],t[rev[i]]);
for (int i=1;i<N;i<<=1) {
for (int j=0;j<i;j++) { //此处一定要预处理,递推精度感人T_T
E tmp(cos(Pi*f*j/i),f*sin(Pi*j/i));
w[j]=tmp;
}
for (int p=i<<1,j=0;j<N;j+=p) {
for (int k=0;k<i;k++) {
E x=t[k+j],y=t[k+j+i]*w[k];
t[k+j]=x+y;t[k+j+i]=x-y;
}
}
}
}
void FFT(LL *u,LL *v,LL p) {
E clean(0,0);
for (int i=0;i<N;i++) a[i]=b[i]=c[i]=d[i]=A[i]=B[i]=C[i]=clean;
for (int i=0;i<=K;i++) {
F[i]=u[i]*fac[K-i]%MOD*power(p,i)%MOD;
G[i]=v[i]*fac[K-i]%MOD;
}
for (int i=0;i<N;i++) {
a[i]=F[i]>>15;b[i]=F[i]&(M-1);
c[i]=G[i]>>15;d[i]=G[i]&(M-1);
}
DFT(a,1);DFT(b,1);DFT(c,1);DFT(d,1);
for (int i=0;i<N;i++) {
A[i]=a[i]*c[i];
B[i]=a[i]*d[i]+b[i]*c[i];
C[i]=b[i]*d[i];
}
DFT(A,-1);DFT(B,-1);DFT(C,-1);
for (int i=0;i<=K;i++) {
LL X=(LL)(A[i].real()/N+0.5)%MOD;
LL Y=(LL)(B[i].real()/N+0.5)%MOD;
LL Z=(LL)(C[i].real()/N+0.5)%MOD;
u[i]=((X<<30)+(Y<<15)+Z)%MOD;
}
for (int i=0;i<=K;i++) u[i]=u[i]*ifac[K]%MOD*ifac[K-i]%MOD;
} int main() {
scanf("%lld%lld",&n,&K);
if (n>K) {puts("0");return 0;}
for (N=1,L=-1;N<=2*K;N<<=1) L++;
for (int i=0;i<N;i++) rev[i]=(rev[i>>1]>>1) | ((i&1)<<L);
fac[0]=ifac[0]=1;
for (LL i=1;i<=K;i++) {
fac[i]=fac[i-1]*i%MOD;
ifac[i]=power(fac[i],MOD-2);
}
g[0]=1;
for (LL x=1,i=1;i<=K;i++) {
x=x*(K-i+1)%MOD*power(i,MOD-2)%MOD;
f[i]=x;
}
LL p=2;
while (n) {
if (n&1) FFT(g,f,p);
n>>=1;FFT(f,f,p);
p=p*p%MOD;
}
LL res=0;
for (int i=0;i<=K;i++) res=(res+g[i])%MOD;
printf("%lld",res);
return 0;
}

  

【codeforces 623E】 Transforming Sequence的更多相关文章

  1. 【codeforces 466D】Increase Sequence

    [题目链接]:http://codeforces.com/problemset/problem/466/D [题意] 给你n个数字; 让你选择若干个区间; 且这些区间[li,ri]; 左端点不能一样; ...

  2. 【codeforces 602D】Lipshitz Sequence

    time limit per test1 second memory limit per test256 megabytes inputstandard input outputstandard ou ...

  3. 【CodeForces 622A】Infinite Sequence

    题意 一个序列是, 1, 2, 1, 2, 3, 1, 2, 3, 4, 1, 2, 3, 4, 5....这样排的,求第n个是什么数字. 分析 第n个位置属于1到k,求出k,然后n-i*(i-1)/ ...

  4. 【codeforces 623E】dp+FFT+快速幂

    题目大意:用$[1,2^k-1]$之间的证书构造一个长度为$n$的序列$a_i$,令$b_i=a_1\ or\ a_2\ or\ ...\ or a_i$,问使得b序列严格递增的方案数,答案对$10^ ...

  5. 【codeforces 415D】Mashmokh and ACM(普通dp)

    [codeforces 415D]Mashmokh and ACM 题意:美丽数列定义:对于数列中的每一个i都满足:arr[i+1]%arr[i]==0 输入n,k(1<=n,k<=200 ...

  6. 【47.40%】【codeforces 743B】Chloe and the sequence

    time limit per test1 second memory limit per test256 megabytes inputstandard input outputstandard ou ...

  7. 【codeforces 438D】The Child and Sequence

    [原题题面]传送门 [大致题意] 给定一个长度为n的非负整数序列a,你需要支持以下操作: 1:给定l,r,输出a[l]+a[l+1]+…+a[r]. 2:给定l,r,x,将a[l],a[l+1],…, ...

  8. 【25.00%】【codeforces 584E】Anton and Ira

    time limit per test1 second memory limit per test256 megabytes inputstandard input outputstandard ou ...

  9. 【66.47%】【codeforces 556B】Case of Fake Numbers

    time limit per test2 seconds memory limit per test256 megabytes inputstandard input outputstandard o ...

随机推荐

  1. currentBackgroundImage:获取按钮背景图片

    NSData *imagedata1=UIImagePNGRepresentation(btn.currentBackgroundImage);//按钮背景图片转NSData NSData *imag ...

  2. Liunx-cp命令

    1. 复制当前目录的test文件夹 到/201904 目录 出现如下截图问题是因为test目录下还有文件,所以得加-r,使用递归拷贝.我现在用这个命令拷贝文件都加-r了,不管有文件还是没文件 2.复制 ...

  3. BQMeetup

    BQMeetup 时间:2017.12.19 地点:北京东城区东直门国华投资大厦1105

  4. 20155207 EXP7 网络欺诈技术防范

    20155207 EXP7 网络欺诈技术防范 实验内容 本实践的目标理解常用网络欺诈背后的原理,以提高防范意识,并提出具体防范方法. 具体有 (1)简单应用SET工具建立冒名网站 (2)etterca ...

  5. 20155211 Exp4 恶意代码分析

    20155211 Exp4 恶意代码分析 实践目标 1 监控你自己系统的运行状态,看有没有可疑的程序在运行. 2 是分析一个恶意软件,就分析Exp2或Exp3中生成后门软件:分析工具尽量使用原生指令或 ...

  6. libgdx学习记录6——动作Action

    libgdx中的Action类能够有效的帮助我们实现位移.旋转.缩放.淡入淡出等效果,对游戏的设计很有用. Action是一个抽象类,本身不可以实例化.一般使用的它的继承类,常用的有 MoveToAc ...

  7. vuex实践之路——笔记本应用(二)

    上一篇我们简单介绍了vuex在此项目中的作用. 这次来理一下项目的整体思路. main.js上次看过了,首先看App.vue文件 我们引入了Toolbar.vue,NodeList.vue,Edito ...

  8. Java中的Calendar日历用法详解

    第一部分 Calendar介绍 public abstract class Calendar implements Serializable, Cloneable, Comparable<Cal ...

  9. C#_正则表达式

    概述 正则表达式,主要是用符号描述了一类特定的文本(模式).而正则表达式引擎则负责在给定的字符串中,查找到这一特定的文本. 本文主要是列出常用的正则表达式符号,加以归类说明.本文仅仅是快速理解了正则表 ...

  10. java保留两位小数4种方法(转载)

    喵喵最近经常遇到小数点保留的问题,转载一篇Java里面的几种小数点位数控制方法. 这是转载的原地址:https://www.cnblogs.com/chenrenshui/p/6128444.html ...