• 【codeforces 623E】 Transforming Sequence


    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;
    }
    

      

  • 相关阅读:
    Win10 蓝屏
    XE Button Color
    IOS 屏幕尺寸
    Delphi 转圈 原型进度条 AniIndicator 及线程配合使用
    Delphi 询问框 汉化
    Delphi Android 询问框
    Delphi BLE 控件
    浮点高低位赋值
    delphi 蓝牙 TBluetoothLE
    16进制字节转换
  • 原文地址:https://www.cnblogs.com/MashiroSky/p/6351225.html
Copyright © 2020-2023  润新知