zoukankan      html  css  js  c++  java
  • CF773F Test Data Generation

    CF773F Test Data Generation

    没能自己推出来/kk

    显然,题目的限制条件就是:

    • 选择奇数个数,且总数 (le max_n)

    • (a_nmod 2=0,dfrac{a_n}{g}mod 2=1)

    直接枚举 (g) 的最高的 (2) 的次幂可以将限制二转化为:在 ([1,dfrac{max_a}{2^k}]) 中选数,最大的数是奇数。

    枚举最大数,枚举选的数的个数可以得到一个 (O(nalog a)) 的暴力(这个 (log) 的来源是:每次传 a=maxa>>i 进去)

    for(int i=1;i<=a;i+=2)
          for(int j=1;j<=n;j+=2)
                ans+=C[i-1][j-1];
    

    推到这里就我推不动了/kk,一直考虑怎么算这个式子发现完全不会。。。然后只好去看题解/kk

    用生成函数 (F(a,p)=sum f(i,a,p)z^i)(f(i,a,p))表示在 ([1,a]) 中选数,最大数奇偶性为 (p) 选了 (i) 个的方案数,并且规定 f(0,x,y)=0,即不包括选 (0) 个数的情况

    然后就是两个很牛逼的转移

    [egin{cases} F(2a,p)=F(a,p)+(F(a,0)+F(a,1)+1)*F(a,poperatorname{xor}(a\%2))\ F(a+1,p)=F(a,p)+[(a+1)\%2=p](F(a,0)+F(a,1)+1) end{cases} ]

    怎么说呢?看到这个转移一下子就能懂,自己就是写不出来/kk

    第一行:在 ([1,2a]) 中选数,相当于只选 (le a) 的,再加上,选一部分 (le a) 的并且加 (a) ,就能出现 (>a) 的数了。

    (如果生成函数看不习惯可以写成卷积的形式,可能更好理解)

    具体来说,前 (i) 个数 (le a) 并且随便选,后 (n-i) 个数 (le a) 然后加 (a) ,同时要保证最大数的奇偶性,就有了第一行转移。妙啊!

    第二行:分选 (a+1) 与不选 (a+1) 来讨论。不选就是 (F(a,p)) ,选 (a+1) 那么 (le a) 的数就随便选了。

    直接倍增FFT求解。但是记住 (g)(2) 的最高次幂不能是 (0) ,所以读进来的 (a) 要除以 (2) 。我tm写着写着忘掉了,白调了一个小时/kk

    另外,这题并不用MTT,(1e5) 以内卷起来不会有精度问题,最大卷起来 (1e5*1e5*3e4=3e14) ,而且远达不到,炸不掉 double 的精度,好调好写跑得快。

    虽然这题要对 (log a)(a) 求值,但是显然,每倍增一位就统计一次答案可以随手消掉这个 (log a) ,总复杂度还是倍增FFT的复杂度 (O(nlog nlog a))

    #include<bits/stdc++.h>
    using namespace std;
    #define fi first
    #define se second
    #define mkp(x,y) make_pair(x,y)
    #define pb(x) push_back(x)
    #define sz(v) (int)v.size()
    typedef long long LL;
    typedef double db;
    template<class T>bool ckmax(T&x,T y){return x<y?x=y,1:0;}
    template<class T>bool ckmin(T&x,T y){return x>y?x=y,1:0;}
    #define rep(i,x,y) for(int i=x,i##end=y;i<=i##end;++i)
    #define per(i,x,y) for(int i=x,i##end=y;i>=i##end;--i)
    inline int read(){
    	int x=0,f=1;char ch=getchar();
    	while(!isdigit(ch)){if(ch=='-')f=0;ch=getchar();}
    	while(isdigit(ch))x=x*10+ch-'0',ch=getchar();
    	return f?x:-x;
    }
    const int N=30005;
    const int M=N<<2;
    int n,a,mod,f[2][M],ans;
    int fmod(int x){return x-=mod,x+=x>>31&mod,x;}
    
    namespace poly{
    const db PI=acos(-1);
    struct cp{
    	db x,y;
    	cp(){x=y=0;}
    	cp(db x_,db y_){x=x_,y=y_;}
    	cp operator + (const cp&t)const{return cp(x+t.x,y+t.y);}
    	cp operator - (const cp&t)const{return cp(x-t.x,y-t.y);}
    	cp operator * (const cp&t)const{return cp(x*t.x-y*t.y,x*t.y+y*t.x);}
    }w[M];
    int rev[M],lim,lg;
    void init(const int&n){
    	for(lg=0,lim=1;lim<n;++lg,lim<<=1);
    	for(int i=0;i<lim;++i)rev[i]=(rev[i>>1]>>1)|((i&1)<<(lg-1)),w[i]=cp(cos(2*PI*i/lim),sin(2*PI*i/lim));
    }
    void FFT(cp*a,int op){
    	for(int i=0;i<lim;++i)if(i>rev[i])swap(a[i],a[rev[i]]);
    	for(int i=1,t=lim>>1;i<lim;i<<=1,t>>=1){
    		for(int j=0;j<lim;j+=i<<1){
    			for(int k=0;k<i;++k){
    				const cp X=a[j+k],Y=w[k*t]*a[i+j+k];
    				a[j+k]=X+Y,a[i+j+k]=X-Y;
    			}
    		}
    	}
    	if(op)return;
    	for(int i=0;i<lim;++i)a[i].x/=lim;
    }
    void mul(int*f,int*g,int*ans){
    	static cp A[M],B[M];
    	for(int i=0;i<lim;++i)A[i]=cp(f[i],0),B[i]=cp(g[i],0);
    	FFT(A,1),FFT(B,1);
    	for(int i=0;i<lim;++i)A[i]=A[i]*B[i],w[i].y*=-1;
    	FFT(A,0);
    	for(int i=0;i<lim;++i)ans[i]=LL(A[i].x+0.5)%mod;
    	for(int i=0;i<lim;++i)w[i].y*=-1;
    }
    #define clr(a,n) memset(a,0,sizeof(int)*(n))
    void shift(const int&n,const int&a){
    	static int g[M],h[M],q[M];
    	clr(g,lim),clr(h,lim),clr(q,lim),g[0]=1;
    	for(int i=1;i<=n;++i)g[i]=fmod(f[0][i]+f[1][i]);
    	mul(g,f[a&1],h),mul(g,f[(a&1)^1],q);
    	for(int i=1;i<=n;++i)f[0][i]=fmod(f[0][i]+h[i]),f[1][i]=fmod(f[1][i]+q[i]);
    }
    void setbit(const int&n,const int&a){
    	static int g[N];g[0]=1;
    	for(int i=1;i<=n;++i)g[i]=fmod(f[0][i]+f[1][i]),f[1][i]=fmod(f[1][i]+g[i-1]);
    }
    }
    signed main(){
    	n=read(),a=read()>>1,mod=read();
    	if(!a)return puts("0"),0;
    	f[1][1]=ans=1,poly::init(n<<1);
    	for(int i=log2(a)-1,len=1;i>=0;--i){
    		poly::shift(n,len),len<<=1;
    		if(a>>i&1)poly::setbit(n,len),++len;
    		for(int j=1;j<=n;j+=2)ans=fmod(ans+f[1][j]);
    	}
    	printf("%d
    ",ans);
    	return 0;
    }
    
  • 相关阅读:
    django自带登录认证与登录自动跳转
    11月份草稿2
    使用JavaScript实现字符串格式化
    requests与BeautifulSoup
    python+minicap(二)
    python+minicap的使用
    python+opencv图像处理(一)
    haproxy实现mysql从库负载均衡
    mysql 5.7 64位 解压版安装
    Redis基础教程
  • 原文地址:https://www.cnblogs.com/zzctommy/p/14205673.html
Copyright © 2011-2022 走看看