zoukankan      html  css  js  c++  java
  • 【LOJ #547】【LibreOJ β Round #7】—匹配字符串(常系数齐次线性递推+容斥+Lucas)

    传送门

    f[i]f[i]表示前ii个全部合法且最后一个为00的方案数
    那么可以得到f[i]=j=1mf[ij]f[i]=sum_{j=1}^mf[i-j]
    ssff前缀和
    那么有
    f[i]=s[i1]s[im1]f[i]=s[i-1]-s[i-m-1]
    s[i]s[i1]=s[i1]s[im1]s[i]-s[i-1]=s[i-1]-s[i-m-1]
    s[i]=2s[i1]s[im1]s[i]=2*s[i-1]-s[i-m-1]
    这样就有一个O(m)O(m)的递推式了
    多项式取模可以做到O(mlogmlogn)O(mlogmlogn)

    考虑如果mm比较大的时候
    可以容斥有几段全黑串
    那么有ans=i=0nm+1(1)i(nimi)2n(m+1)ians=sum_{i=0}^{frac{n}{m+1}}(-1)^i{n-imchoose i}2^{n-(m+1)i}
    模数很小做个LucasLucas就完了
    这样是O(nmlogn)O(frac n mlogn)
    对数据分类做一下就可以了

    才发现自己线性递推的板子是错的,为此调了一年

    #include<bits/stdc++.h>
    using namespace std;
    const int RLEN=1<<20|1;
    inline char gc(){
        static char ibuf[RLEN],*ib,*ob;
        (ob==ib)&&(ob=(ib=ibuf)+fread(ibuf,1,RLEN,stdin));
        return (ob==ib)?EOF:*ib++;
    }
    #define gc getchar
    inline int read(){
        char ch=gc();
        int res=0,f=1;
        while(!isdigit(ch))f^=ch=='-',ch=gc();
        while(isdigit(ch))res=(res+(res<<2)<<1)+(ch^48),ch=gc();
        return f?res:-res;
    }
    #define ll long long
    #define re register
    #define pii pair<int,int>
    #define fi first
    #define se second
    #define pb push_back
    #define cs const
    #define bg begin
    #define poly vector<int>
    #define int long long
    const int mod=65537,G=3;
    inline int add(int a,int b){return a+b>=mod?a+b-mod:a+b;}
    inline void Add(int &a,int b){a=add(a,b);}
    inline int dec(int a,int b){return a>=b?a-b:a-b+mod;}
    inline void Dec(int &a,int b){a=dec(a,b);}
    inline int mul(int a,int b){return 1ll*a*b%mod;}
    inline void Mul(int &a,int b){a=mul(a,b);}
    inline int ksm(int a,int b,int res=1){for(;b;b>>=1,a=mul(a,a))(b&1)?(res=mul(res,a)):0;return res;}
    inline int Inv(int x){return ksm(x,mod-2);}
    inline void chemx(int &a,int b){a<b?a=b:0;}
    inline void chemn(int &a,int b){a>b?a=b:0;}
    cs int C=16;
    cs int N=(1<<17)+5;
    namespace solve1{
    	poly w[C+1];
    	inline void init_w(){
    		for(int i=1;i<=C;i++)w[i].resize(1<<(i-1));
    		w[C][0]=1;
    		int wn=ksm(G,(mod-1)/(1<<C));
    		for(int i=1;i<(1<<(C-1));i++)w[C][i]=mul(w[C][i-1],wn);
    		for(int i=C-1;i;i--)
    		for(int j=0;j<(1<<(i-1));j++)w[i][j]=w[i+1][j<<1];
    	}
    	int rev[(1<<C)<<2];
    	inline void init_rev(int lim){
    		for(int i=0;i<lim;i++)rev[i]=(rev[i>>1]>>1)|((i&1)*(lim>>1));
    	}
    	inline void ntt(poly &f,int lim,int kd){
    		for(int i=0;i<lim;i++)if(i>rev[i])swap(f[i],f[rev[i]]);
    		for(int mid=1,l=1,a0,a1;mid<lim;mid<<=1,l++)
    		for(int i=0;i<lim;i+=(mid<<1))
    		for(int j=0;j<mid;j++)
    		a0=f[i+j],a1=mul(w[l][j],f[i+j+mid]),f[i+j]=add(a0,a1),f[i+j+mid]=dec(a0,a1);
    		if(kd==-1){
    			reverse(f.bg()+1,f.bg()+lim);
    			for(int i=0,inv=Inv(lim);i<lim;i++)Mul(f[i],inv);
    		}
    	}
    	inline poly operator +(poly a,poly b){
    		if(a.size()<b.size())a.resize(b.size());
    		for(int i=0;i<b.size();i++)Add(a[i],b[i]);
    		return a;
    	}
    	inline poly operator -(poly a,poly b){
    		if(a.size()<b.size())a.resize(b.size());
    		for(int i=0;i<b.size();i++)Dec(a[i],b[i]);
    		return a;
    	}
    	inline poly operator *(poly a,poly b){
    		int deg=a.size()+b.size()-1,lim=1;
    		if(deg<=32){
    			poly c(deg,0);
    			for(int i=0;i<a.size();i++)
    			for(int j=0;j<b.size();j++)
    			Add(c[i+j],mul(a[i],b[j]));
    			return c;
    		}
    		while(lim<deg)lim<<=1;
    		init_rev(lim);
    		a.resize(lim),ntt(a,lim,1);
    		b.resize(lim),ntt(b,lim,1);
    		for(int i=0;i<lim;i++)Mul(a[i],b[i]);
    		ntt(a,lim,-1),a.resize(deg);
    		return a;
    	}
    	inline poly Inv(poly a,int deg){
    		poly b(1,ksm(a[0],mod-2)),c;
    		for(int lim=4;lim<(deg<<2);lim<<=1){
    			c=a,c.resize(lim>>1);
    			init_rev(lim);
    			c.resize(lim),ntt(c,lim,1);
    			b.resize(lim),ntt(b,lim,1);
    			for(int i=0;i<lim;i++)Mul(b[i],dec(2,mul(b[i],c[i])));
    			ntt(b,lim,-1),b.resize(lim);
    		}b.resize(deg);return b;
    	}
    	inline poly operator /(poly a,poly b){
    		int deg=(int)a.size()-(int)b.size()+1;
    		reverse(a.bg(),a.end());
    		reverse(b.bg(),b.end());
    		b=Inv(b,deg),a=a*b,a.resize(deg);
    		reverse(a.bg(),a.end());
    		return a;
    	}
    	inline poly operator %(poly a,poly b){
    		if(a.size()<=b.size())return a;
    		a=a-(a/b)*b,a.resize(b.size()-1);return a;
    	}
    	inline poly ksm(poly a,ll b,poly res,cs poly &mod){
    		for(;b;b>>=1,a=a*a%mod)if(b&1)res=res*a%mod;
    		return res;
    	}
    	namespace CH{
    		inline int solve(poly coef,int *a,ll k){
    			int n=coef.size(),init_w();
    			poly f(n),g(2),res(1,0);g[1]=res[0]=1;
    			for(int i=1; i<n;i++)f[n-i-1]=dec(0,coef[i]);
    			f[n-1]=1;
    			res=ksm(g,k,res,f);
    			int anc=0;
    			for(int i=0;i<res.size();i++)Add(anc,mul(res[i],a[i+1]));
    			return anc;
    		}
    	}
    	namespace BM{
    		poly r[N];
    		int a[N],fail[N],del[N],cnt,n;
    		inline void update(int i){
    			cnt++;
    			int MUL=mul(dec(a[i],del[i]),::Inv(dec(a[fail[cnt-2]],del[fail[cnt-2]])));
    			r[cnt].resize(i-fail[cnt-2],0);
    			r[cnt].pb(MUL);
    			for(int j=1;j<r[cnt-2].size();j++)
    			r[cnt].pb(mul(dec(0,r[cnt-2][j]),MUL));
    			r[cnt]=r[cnt]+r[cnt-1];
    		}
    		inline void B_M(){
    			for(int i=1;i<=n;i++){
    				for(int j=1;j<r[cnt].size();j++)
    				Add(del[i],mul(r[cnt][j],a[i-j]));
    				if(del[i]!=a[i]){
    					fail[cnt]=i;
    					if(!cnt)r[++cnt].resize(i+1);
    					else update(i);
    				}
    			}
    		}
    		inline int solve(int *v,int len,ll m1,ll m2){
    			n=len;
    			for(int i=1;i<=n;i++)a[i]=v[i-1];
    			B_M();
    			int f1=CH::solve(r[cnt],a,m1),f2=CH::solve(r[cnt],a,m2);
    			return dec(f1,f2);
    		}
    	}
    	int f[N*5];
    	inline void main(ll n,ll m){
    		f[0]=1;init_w();
    		for(int i=1;i<=m*3+20;i++){
    			f[i]=mul(f[i-1],2);
    			if(i>m)Dec(f[i],f[i-m-1]);
    		}
    		cout<<BM::solve(f,3*m+21,n+1,n);
    	}
    }
    namespace solve2{
    	int fac[mod],ifac[mod];
    	inline void init(){
    		fac[0]=ifac[0]=1;
    		for(int i=1;i<mod;i++)fac[i]=mul(fac[i-1],i);
    		ifac[mod-1]=Inv(fac[mod-1]);
    		for(int i=mod-2;i;i--)ifac[i]=mul(ifac[i+1],i+1);
    	}
    	inline int C(int n,int m){
    		return n<m?0:mul(fac[n],mul(ifac[m],ifac[n-m]));
    	}
    	inline int Lucas(ll n,ll m){
    		if(n<m)return 0;
    		if(n<mod&&m<mod)return C(n,m);
    		return mul(C(n%mod,m%mod),Lucas(n/mod,m/mod));
    	}
    	inline int calc(ll n,ll m){
    		int res=0,f1=ksm(2,n%(mod-1)),f2=Inv(ksm(2,(m+1)%(mod-1)));
    		for(ll i=0,lim=n/(m+1);i<=lim;i++){
    			int now=mul(Lucas(n-i*m,i),f1);
    			if(i&1)Dec(res,now);
    			else Add(res,now);
    			Mul(f1,f2);
    		}
    		return res;
    	}
    	inline void main(ll n,ll m){
    		init();
    		cout<<dec(calc(n+1,m),calc(n,m))<<'
    ';
    	}
    }
    signed main(){
    	#ifdef Stargazer
    	freopen("lx.cpp","r",stdin);
    	#endif
    	ll n,m;
    	cin>>n>>m;
    	if(m<(1<<14))solve1::main(n,m);
    	else solve2::main(n,m);
    }
    
  • 相关阅读:
    TCP粘包,产生的原因以及解决方案
    php判断变量是否为正整数
    php函数trim中文编码问题解决
    win10设置开机自动启动vagrant虚拟机
    Can't connect to local MySQL server through socket '/var/lib/mysql/mysql.sock' (2)
    git push 时 fatal: Unable to create 'D:/phpStudy/WWW/green_tree/.git/index.lock': File exists.解决办法
    git push 提示 Everything up-to-date
    Allowed memory size of 134217728 bytes exhausted (tried to allocate 2 bytes)
    访问远程mysql数据库,出现报错,显示“1130
    改变网页选中文本的颜色
  • 原文地址:https://www.cnblogs.com/stargazer-cyk/p/12328575.html
Copyright © 2011-2022 走看看