zoukankan      html  css  js  c++  java
  • 【LOJ #3114】【SDOI2019】—移动金币(博弈论+数位dp)

    传送门

    首先这个很套路的转化成阶梯NimNim,把相邻的空看做石子
    问题就变成有nmn-m个石子,放在m+1m+1个阶梯,先手必胜的状态

    考虑先手必败是奇数位置异或和为00
    于是可以数位dpdp

    考虑先枚举给奇数填多少个,把剩下填给偶数
    f[i][j]f[i][j]表示前ii位,还剩jj个石子,异或和为0的方案数
    只需要枚举这一位选几个(当然必须是偶数个)
    然后就完了

    总方案和分配给偶数就是插板法随便算一下就完了

    复杂度O(nmlog)O(nmlog)

    #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++;
    }
    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>
    cs int mod=1e9+9;
    inline int add(int a,int b){return (a+=b)>=mod?a-mod:a;}
    inline int dec(int a,int b){return (a-=b)<0?a+mod:a;}
    inline int mul(int a,int b){return 1ll*a*b%mod;}
    inline void Add(int &a,int b){(a+=b)>=mod?a-=mod:0;}
    inline void Dec(int &a,int b){(a-=b)<0?a+=mod:0;}
    inline void Mul(int &a,int b){a=1ll*a*b%mod;}
    inline int ksm(int a,int b,int res=1){for(;b;b>>=1,Mul(a,a))(b&1)&&(Mul(res,a),1);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 N=150005,M=55;
    int f[22][N],n,m,num,tot,ou,fac[N+M],ifac[N+M];
    inline void init(){
    	cs int len=150050;
    	fac[0]=ifac[0]=1;
    	for(int i=1;i<=len;i++)fac[i]=mul(fac[i-1],i);
    	ifac[len]=Inv(fac[len]);
    	for(int i=len-1;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]));
    }
    int main(){
    	init();
    	n=read(),m=read(),num=(m+1)/2,ou=m-num+1,tot=n-m;
    	f[20][tot]=1;
    	for(int i=19;~i;i--)
    	for(int j=0;j<=tot;j++){
    		for(int k=0;j+(1<<i)*k<=tot&&k<=num;k+=2)
    			Add(f[i][j],mul(f[i+1][j+(1<<i)*k],C(num,k)));
    	}	
    	int res=0;
    	for(int j=0;j<=tot;j++){
    		Add(res,mul(f[0][j],C(j+ou-1,ou-1)));
    	}
    	int ans=C(n,m);
    	cout<<dec(ans,res)<<'
    ';
    }
    
  • 相关阅读:
    使用四元数点乘比较插值是否即将完成
    ShadowGun Demo学习(非技术向)
    测试-关于Unity获取子层级内容的几种接口(Transform FindChild, Component GetComponentInChildren,...)
    Javascript事件模型系列(二)事件的捕获-冒泡机制及事件委托机制
    Javascript事件模型系列(一)事件及事件的三种模型
    在代码中设置IE9的默认文档模式
    如何在博客园的文章/随笔中添加可运行的js代码
    jquery插件:仿百度首页可展开收起的消息提示控件
    有“镜头感”的网页是如何实现的
    HTML5 history API实践
  • 原文地址:https://www.cnblogs.com/stargazer-cyk/p/12328519.html
Copyright © 2011-2022 走看看