zoukankan      html  css  js  c++  java
  • luoguP7468 [NOI Online 2021 提高组] 愤怒的小N

    有序列01序列(s)初始为(0),每次(s)变成(soverline s)(overline s)表示(s)取反。进行无数次。

    现在求:(sum_{i=0}^{n-1} s_if(i)),其中(f(x)=sum_{i=0}^{K-1}a_ix^i)

    (lg nle 5*10^5)(读入二进制)

    (Kle 500)


    (g_0(x)=f(x))(g_{k+1}(x)=g_k(x)-g_k(x+2^k))

    暴力求出(g_k(x)),最后再组合一下就能得到答案。这是(O(K^2lg n))的做法。

    如果在比赛的时候打表,可以发现当(kge K)(g_k(x)=0)。于是就可以得到(O(K^3))的做法。

    推导一下性质:

    [g_k(x)=sum_{i=0}^{2^k-1}g_0(x+i)(-1)^{pc(i)}\ =sum_{t=0}^{K-1}x^tsum_{j=0}^{K-t-1}a_{j+t}inom{j+t}{t}sum_{i=0}^{2^k-1}(-1)^{pc(i)}i^j ]

    探究(sum_{i=0}^{2^k-1}(-1)^{pc(i)}i^j)的性质。设(P_k(x)=sum p_ix^i,p_i=(-1)^{pc(i)}[0le ile 2^k-1])。代入(P_k(e^x))有:

    [P_k(e^x)=sum p_ie^{ix}\ =sum p_isum_{jge 0} frac{(ix)^j}{j!}\ ]

    提取([x^j])得到:([x^j]j!P_k(e^x)=sum p_i i^j)。恰好就是我们要求的东西。又有:

    [P_k(x)=prod_{i=0}^{k-1}(1-x^{2^i})\ P_k(e^x)=x^kprod_{i=0}^{k-i}(-sum_{jge 1}frac{2^{ij}x^{j-1}}{j!}) ]

    于是得到:如果(j<k),则([x^j]j!P_k(e^x)=0)。然后就可以解释前面的结论。


    using namespace std;
    #include <bits/stdc++.h>
    #define L 500005
    #define N 1005
    #define ll long long
    #define mo 1000000007
    ll qpow(ll x,ll y=mo-2){
    	ll r=1;
    	for (;y;y>>=1,x=x*x%mo)
    		if (y&1)
    			r=r*x%mo;
    	return r;	
    }
    int n,K;
    ll nn;
    int b[L];
    ll pw[N*N],C[N][N],inv[N];
    ll g[N][N],f[N];
    void init(int n){
    	pw[0]=1;
    	for (int i=1;i<=n*n;++i)
    		pw[i]=pw[i-1]*2%mo;
    	for (int i=0;i<=n;++i){
    		C[i][0]=1;
    		for (int j=1;j<=i;++j)
    			C[i][j]=(C[i-1][j-1]+C[i-1][j])%mo;
    	}
    	inv[1]=1;
    	for (int i=2;i<=n;++i)
    		inv[i]=(mo-mo/i)*inv[mo%i]%mo;
    }
    ll getsum0(){
    	static ll S[N][N];
    	S[0][0]=1;
    	for (int i=1;i<=K;++i)
    		for (int j=1;j<=i;++j)
    			S[i][j]=(S[i-1][j-1]+j*S[i-1][j])%mo;
    	ll sum=0;
    	for (int k=0;k<K;++k){
    		ll tmp=0;
    		for (int i=0;i<=k;++i){
    			ll pro=1;
    			for (int j=nn-i;j<=nn;++j)
    				pro=pro*j%mo;
    			(tmp+=S[k][i]*inv[i+1]%mo*pro)%=mo;
    		}
    		(sum+=tmp*g[0][k])%=mo;
    	}
    	return sum;
    }
    int main(){
    	static char str[L];
    	scanf("%s",str);
    	n=strlen(str);
    	for (int i=0;i<n;++i)
    		b[i]=str[n-1-i]-'0';
    	for (int i=0,w=1;i<n;++i,w=w*2%mo)
    		(nn+=b[i]*w)%=mo;
    	scanf("%d",&K);
    	for (int i=0;i<K;++i)
    		scanf("%d",&g[0][i]);
    	init(K);
    	ll sum0=getsum0(),sum1=0;
    	for (int k=0;k<K;++k)
    		for (int j=0;j<K;++j){
    			ll sum=0;
    			for (int i=j;i<K;++i)
    				(sum+=g[k][i]*pw[k*(i-j)]%mo*C[i][j])%=mo;
    			g[k+1][j]=(g[k][j]-sum+mo)%mo;
    		}
    	int c=1;
    	for (int k=n-1,of=0;k>=0;--k)
    		if (b[k]){
    			if (k<K){
    				ll sum=0;
    				for (int i=0;i<K;++i)
    					(sum+=g[k][i]*qpow(of,i))%=mo;
    				sum1+=sum*c;
    			}
    			c*=-1;
    			(of+=qpow(2,k))%=mo;
    		}
    	ll ans=(sum0-sum1)*qpow(2)%mo;
    	ans=(ans+mo)%mo;
    	printf("%lld
    ",ans);
    	return 0;
    }
    
  • 相关阅读:
    CF932E Team Work(第二类斯特林数)
    BZOJ 3732: Network(Kruskal重构树)
    BZOJ 2753: [SCOI2012]滑雪与时间胶囊(最小生成树)
    BZOJ 2286: [Sdoi2011]消耗战(虚树+树形dp)
    hdu 4336 Card Collector(状压dp/Min-Max反演)
    BZOJ 3622: 已经没有什么好害怕的了(二项式反演)
    BZOJ 2839: 集合计数(二项式反演)
    CF gym 101933 K. King's Colors(二项式反演)
    BZOJ 1101: [POI2007]Zap(莫比乌斯反演)
    BZOJ 3747: [POI2015]Kinoman(线段树)
  • 原文地址:https://www.cnblogs.com/jz-597/p/14586665.html
Copyright © 2011-2022 走看看