性质分析+数位DPCF750G New Year and Binary Tree Paths

Posted psychicboom

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了性质分析+数位DPCF750G New Year and Binary Tree Paths相关的知识,希望对你有一定的参考价值。

规律找完,不会DP,光荣爆零,身败名裂

而且这还是道原题!!原题!!


从只往一棵子树走的情况考虑

(x)往左走了(z)个儿子,那总和为(xsumlimits_{i=0}^{z}2^i=x(2^{z+1}-1))

考虑从上到下第(y(yin(2,z]))个儿子变成了右儿子,其它不变,则贡献为(xsumlimits_{i=0}^{z}2^i+sumlimits_{i=0}^{z-y}2^i=x(2^z-1)+2^{z-y+1}-1)

然后你稍微看一下会发现,当(z)固定时,(x)只能取(lfloor frac{s}{2^z-1} floor),且只有一种走法

现在考虑(x)的左儿子向左下走了(z1)步,右儿子向左下走了(z2)步的情况

则有(2x(2^{z1}-1)+(2x+1)(2^{z2}-1)+2^{z2}-1+x=(2^{z1+1}+2^{z2+1}-3)x+2^{z2}-1)的贡献

然后枚举了(z1),(z2)后,(x)还是只有一个取值,即(lfloor frac{s}{2^{z1+1}+2^{z2+1}-3} floor)

证明的话就考虑左子树和右子树走相同步,左子树最大的路径和一定小于右子树最小的路径和

然后问题转化成了:用({1,3…,2^{h1}-1})({1,3,…,2^{h2}-1})的元素组成(s-lfloor frac{s}{2^{z1+1}+2^{z2+1}-3} floor*(2^{z1+1}+2^{z2+1}-3))的方案数

(s-lfloor frac{s}{2^{z1+1}+2^{z2+1}-3} floor*(2^{z1+1}+2^{z2+1}-3)=res)

这个(-1)很烦,于是你考虑枚举选了(cnt)个数,然后把所有(2^i-1)转化为(2^i),于是显然(res+cnt)为偶数时才有解

(f[i][j][k])表示当前做到第(i)位,选了(j)个数,这位是否进位的方案数

对于(2^j),设第一个集合是否选这个数的状态为(x(xin{0,1})),第二个集合的选择状态为(y(yin{0,1}))

转移时,要满足(x+y+k)(res+cnt)的第(j)位奇偶性相同

于是有(f[i+1][j+x+y][frac{x+y+k}{2}]leftarrow f[i][j][k])

然后就分类只走一边和两边的情况就行了

因为DRX太强了所以这里贴她的代码,我的代码在这里(大半年前写的,码风巨丑无比)

#include<bits/stdc++.h>
using namespace std;
#define rep(i,j,k) for(int i=j;i<=k;++i)
typedef long long ll;
typedef double db;
ll bit[65],f[65][120][2];//在{2,2^2,2^3...2^h1}∪{2,2^2,...2^h2}之间选tot个数,其和==s,                                                                    
inline ll dp(ll s,int tot,int h1,int h2){//应该是{2-1,2^2-1,2^3-1...2^h1-1}∪{2-1,2^2-1,...2^h2-1},但是已经把减一移过去s了
    memset(f,0,sizeof f);f[0][0][0]=1;//在{2,2^2...}中选,2^min(h1,h2)和之前的数可以选两个,f[i][j][k]表示做到第i个数,之前(包括i)选了j个数,对下一位的进位为k
    int ed=log2(s);//能选的最大的数 
    rep(i,1,ed){
        ll d=(s>>i)&1;
        int ed=i*2-2;//在 i之前最多能选多少个 
        rep(j,0,ed) rep(k,0,1)/*上一位是否进位*/rep(p1,0,1)/*左链是否向右走即是否选一个2^i*/rep(p2,0,1)/*右链同理*/if((i<h1||p1==0)&&(i<h2||p2==0)&& (p1+p2+k)%2==d)/*因为x的左右儿子即2^h1和2^h2是肯定要选的*/
        f[i][j+p1+p2][(k+p1+p2)/2]+=f[i-1][j][k]; 
    }
    return f[ed][tot][0];
} 
int main(){
    ll x,s,res,ans=0;
    int ed=0;
    scanf("%lld",&s);
    bit[0]=1;while(bit[ed]<=s) bit[++ed]=bit[ed-1]<<1;
    rep(i,1,ed){//统计一条链的情况 
        if(bit[i]-1>s) break;
        x=s%(bit[i]-1);
        for(int j=i;j>=1;--j) if(x>=bit[j]-1) x-=bit[j]-1;
        if(!x) ++ans;
    }
    rep(h1,1,ed-1){//统计有分叉的情况 
        for(int h2=1;bit[h2]-1<=s&&h2<ed;++h2){//枚举两边的链长 h1  h2 
            x=(s-bit[h2]+1)/(bit[h1+1]+bit[h2+1]-3);
            if(x>0){
                res=(s-bit[h2]+1)%(bit[h1+1]+bit[h2+1]-3);
                if(res==0){//不用向右走 
                    ++ans;continue;
                }
                if(h1==1&&h2==1){//x只选了左儿子x*2和右儿子x*2+1 ,所以是x*5+1 
                    ans+=(s==x*5+1);continue;
                }//有余数说明在某些点要往右走
                rep(i,1,h1+h2) if((res+i)%2==0) ans+=dp(res+i,i,h1,h2);//相当于把减掉的 i个一挪到等式另一边变成加 i个一 
            }
        }
    }
    printf("%lld",ans);
}

以上是关于性质分析+数位DPCF750G New Year and Binary Tree Paths的主要内容,如果未能解决你的问题,请参考以下文章

CF750G New Year and Binary Tree Paths(DP)

数位DPCF55D Beautiful numbers

Codeforces908G. New Year and Original Order

CF908G New Year and Original Order

CF750F New Year and Finding Roots 构造+树论

CF908GNew Year and Original Order 数位DP