【Codeforces 750G】—New Year and Binary Tree Paths(数位dp)
题意:给出一颗无限大的线段树,询问有多少条路径满足点的编号和为
实际上线段树只有层左右
考虑一条路径就是2条向下延伸的链
考虑一条链的情况
实际上如果确定了链的长度,就可以唯一确定一个出发点
证明:
如果链一直向左儿子走,编号和显然为
对于,如果一直向右儿子走
那么编号和为
所以一定等于
考虑在从下往上第个位置如果向右儿子走,贡献是
令
我们就只需要看能否被表示出来
暴力从高往低做就完了
考虑2条链的情况
设左右链的长度为
那么可以得到贡献为
类似的可以证明唯一
即可得到
考虑现在就是用
凑出来(因为第一个左右确定了)
由于有个,考虑枚举一共选了几个数
看能不能凑出来
令表示前位,已经选了个,是否有进位
每次就枚举这一位分别选不选
就完了
复杂度
#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)<<'\n';
}
int main(){
for(int i=0;i<N;i++)bin[i]=1ll<<i;
solve();
}