Анализ недвижимости [DP] + цифровой CF750G Новый год и бинарное дерево Дорожки

Найти закон, не имеет DP, славный взрыв ноль, и гибель

И это путь к оригинальному названию! ! Оригинальное название! !


Из единственного случая, чтобы пойти рассмотреть поддерево

\ (Х \) влево , чтобы перейти \ (Z \) сына , что сумма \ (х \ сумма \ limits_ { г = 0} ^ {Z} 2 ^ г = х (2 ^ {г + 1} - 1) \)

Рассмотренный от верхней части к нижней части \ (у (у \ в ( 2, г]) \) сын сын становится правой, другой постоянной, вклад в \ (х \ сумма \ limits_ { г = 0} ^ { г} 2 ^ г + \ сумма \ limits_ {г = 0} ^ {ZY} 2 ^ г = х (2 ^ г-1) + 2 ^ {гу + 1} -1 \)

Тогда вы увидите , что немного посмотреть, когда \ (Z \) фиксирована, \ (X \) может принимать только \ (\ lfloor \ FRAC {S} {2}. 1-Z ^ \ rfloor \) , и только один вниз Франция

Теперь рассмотрим \ (х \) оставил его сын оставил проворчал \ (z1 \) шагов, сын слева и справа установлены \ (z2 \) случай шаг

Там \ (2x (2 ^ {z1 } -1) + (2х + 1) (2 ^ {z2} -1) + 2 ^ {z2} -1 + х = (2 ^ {z1 + 1} + 2 ^ {z2 + 1} -3) х + 2 ^ {z2} -1 \) вклад

Тогда перечислении \ (Z1 \) , \ (Z2 \) после того, как , \ (Х \) или только значение, то есть, \ (\ \ lfloor гидроразрыва ы { } {2 ^ {z1 + 1} + 2 ^ { z2 + 1} -3} \ rfloor \)

Доказательство, а затем рассмотреть левое поддерево и правое поддерево идут Синхронный, левое поддерево должно быть меньше, чем самый большой из пути и пути наименьшего и правого поддерева

Затем превращается в проблему: с помощью \ (\ {1,3 , ..., 2 ^ {h1} -1 \} \) и \ (\ {1,3, ..., 2 ^ {h2} -1 \} \) из элементы \ (втор- \ lfloor \ гидроразрыва { х} {2 ^ {z1 + 1} + 2 ^ {z2 + 1} -3} \ rfloor * (2 ^ {z1 + 1} + 2 ^ {z2 + 1 } -3) \) является количество программ

\ (втор- \ lfloor \ гидроразрыва {S} {2 ^ {z1 + 1} + 2 ^ {z2 + 1} -3} \ rfloor * (2 ^ {z1 + 1} + 2 ^ {z2 + 1} -3) = Рез \)

\ (--1 \) раздражает, поэтому рассмотрим перечисление выбрали \ (CNT \) число, то все \ (2 ^ я-1 \ ) в \ (2 ^ я \) , то , очевидно , \ (Рез + CNT \) является разрешимой , если четное число

Набор \ (е [I] [J ] [K] \) представляет текущий раздел сделать \ (I \) бит, выбранный \ (J \) число, является ли число программ несут

Для \ (2 ^ J \) , выбран ли набор из первого набора состояния этого числа \ (Х (Х \ в \ {0,1 \}) \) , второе выберите состояние устанавливается \ (У (у \ в \ {0,1 \ }) \)

Когда передача, чтобы удовлетворить \ (х + у + к \ ) и \ (резисторный + CNT \) из \ (\ J) бит четности являются одинаковыми

于是有\ (е [г + 1] [J + х + у] [\ гидроразрыва {х + у + к} {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);
}

рекомендация

отwww.cnblogs.com/PsychicBoom/p/11774327.html
рекомендация