zoukankan      html  css  js  c++  java
  • 【Codeforces 750G】—New Year and Binary Tree Paths(数位dp)

    传送门

    题意:给出一颗无限大的线段树,询问有多少条路径满足点的编号和为k,k1015k,kle10^{15}

    实际上线段树只有5050层左右
    考虑一条路径就是2条向下延伸的链

    考虑一条链的情况
    实际上如果确定了链的长度ll,就可以唯一确定一个出发点xx
    证明:
    如果链一直向左儿子走,编号和显然为(2l+11)x(2^{l+1}-1)x
    对于x1x-1,如果一直向右儿子走
    那么编号和为
    (2l+11)(x1)+i=1ll(2i1)=(2l+11)xl<(2l+11)x(2^{l+1}-1)(x-1)+sum_{i=1}^{l-l}(2^{i}-1)=(2^{l+1}-1)x-l<(2^{l+1}-1)x

    所以xx一定等于k2l+11lfloorfrac{k}{2^{l+1}-1} floor
    考虑在从下往上第ii个位置如果向右儿子走,贡献是2i12^i-1
    res=k(2l+11)xres=k-(2^{l+1}-1)x
    我们就只需要看resres能否被211,221.....2l12^1-1,2^2-1.....2^l-1表示出来
    暴力从高往低做就完了

    考虑2条链的情况
    设左右链的长度为l,rl,r
    那么可以得到贡献为(2l+1+2r+13)x+2r1(2^{l+1}+2^{r+1}-3)x+2^r-1
    类似的可以证明xx唯一
    即可得到resres
    考虑现在就是用211,221,.....,2l11,211,221....2r112^1-1,2^2-1,.....,2^{l-1}-1,2^1-1,2^2-1....2^{r-1}-1
    凑出resres来(因为第一个左右确定了)

    由于有个1-1,考虑枚举一共选了几个数kk
    看能不能凑出res+kres+k
    f[i][j][0/1]f[i][j][0/1]表示前ii位,已经选了jj个,是否有进位
    每次就枚举l,rl,r这一位分别选不选
    dpdp就完了

    复杂度O(log5)O(log^5)

    #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
    inline ll readl(){
        char ch=gc();
        ll 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 re register
    #define pii pair<int,int>
    #define fi first
    #define se second
    #define pb push_back
    #define cs const
    #define bg begin
    const int mod=998244353;
    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?1ll*a*b%mod:a*b;}
    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 N=57;
    ll bin[N];
    inline ll solve1(ll x,ll y){
    	ll res=0;
    	while(x!=y){
    		if(x<y)swap(x,y);
    		res+=x,x>>=1;
    	}
    	res+=x;return res;
    }
    ll f[N][N*2][2];
    inline ll dp(ll mx,int l,int r,int t){
    	memset(f,0,sizeof(f));
    	f[0][0][0]=1;int len=1;
    	for(int i=1;bin[i-1]<=mx;i++,len++){
    		int d=(mx>>i)&1;
    		for(int j=0;j<=t;j++){
    			for(int x=0;x<=1;x++)
    			if(x!=1||i<l)
    			for(int y=0;y<=1;y++)
    			if(y!=1||i<r){
    				if((x+y)%2==d)f[i][j+x+y][(x+y)/2]+=f[i-1][j][0];
    				else f[i][j+x+y][(x+y+1)/2]+=f[i-1][j][1];
    			}
    		}
    	}
    	return f[len-1][t][0];
    }
    inline ll solve2(ll s){
    	ll ans=0;
    	for(int i=0;bin[i]<=s;i++)
    	for(int j=0;bin[j]<=s;j++){
    		ll x=(s-bin[j]+1)/(bin[i+1]+bin[j+1]-3);
    		if(!x)continue;
    		ll res=s-bin[j]+1-(bin[i+1]+bin[j+1]-3)*x;
    		if(!res){ans++;continue;}
    		for(int k=1;k<=i+j-(i!=0)-(j!=0);k++)
    		if((res+k)%2==0)ans+=dp(res+k,i,j,k);
    	}
    	return ans;
    }
    inline void solve(){
    	ll d=readl();
    	cout<<solve2(d)<<'
    ';
    }
    int main(){
    	for(int i=0;i<N;i++)bin[i]=1ll<<i;
    	solve();
    }
    
  • 相关阅读:
    TCP与UDP在socket编程中的区别
    使用python selenium webdriver模拟浏览器
    Web性能测试参数
    DPDK学习之开篇介绍
    go环境import cycle not allowed问题处理
    使用etcd+confd管理nginx配置
    服务的扩展性
    linux 网络编程
    单片机成长之路(stm8基础篇)- 025 stm8 时钟切换
    单片机成长之路(51基础篇)- 024 基于 N76E003 的按键按键状态机
  • 原文地址:https://www.cnblogs.com/stargazer-cyk/p/12328597.html
Copyright © 2011-2022 走看看