zoukankan      html  css  js  c++  java
  • 【题解】Luogu P5342 [TJOI2019]甲苯先生的线段树

    原题传送门

    挺有趣的一道题

    (c=1),暴力求出点权和n即可

    (c=2),先像(c=1)一样暴力求出点权和n,考虑有多少路径点权和也为n

    考虑设x为路径的转折点,(L)(x)向左儿子走的长度,(R)(x)向右儿子走的长度。易知当(L,R)确定时,有唯一的(x)对应

    (x)为转折点,(L,R)为向左/右儿子走的距离,这时点权和至少为(Min=(2^{L+1}+2^{R+1}-3)x+2^R-1)

    此时x的取值一定珂以求出。考虑一下如何产生剩下(n-Min)的贡献,这个贡献一定是原来向左儿子走改成向右儿子走所带来的

    我们珂以进行记忆化搜索求出答案,记录(f[i][j][k])表示为向左/右儿子走的距离为(i,j)还差贡献为(k)的方案数(注意:答案要减去原来已有的那个解)

    #include <bits/stdc++.h>
    #define ll long long 
    #define getchar nc
    using namespace std;
    inline char nc(){
        static char buf[100000],*p1=buf,*p2=buf;
        return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
    }
    inline ll read()
    {
        register ll x=0,f=1;register char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9')x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
        return x*f;
    }
    inline void write(register ll x)
    {
        if(!x)putchar('0');if(x<0)x=-x,putchar('-');
        static int sta[20];register int tot=0;
        while(x)sta[tot++]=x%10,x/=10;
        while(tot)putchar(sta[--tot]+48);
    }
    inline int Max(register int x,register int y)
    {
    	return x>y?x:y;
    }
    inline int dep(register ll n)
    {
    	int res=0;
    	while(n)
    		++res,n>>=1;
    	return res;
    }
    map<ll,ll> mp[55][55];
    inline ll dfs(register int x,register int y,register ll z)
    {
    	if(x<y)
    		x^=y^=x^=y;
    	if(z<0||z>(2ll<<x)+(2ll<<y)-x-y-4)
    		return 0;
    	if(!x&&!y)
    		return !z;
    	if(mp[x][y].count(z))
    		return mp[x][y][z];
    	return mp[x][y][z]=dfs(x-1,y,z)+dfs(x-1,y,z-(1ll<<x)+1);
    }
    int T,d,c;
    ll a,b,n,ans;
    int main()
    {
    	T=read();
    	while(T--)
    	{
    		n=0;
    		d=read(),a=read(),b=read(),c=read();
    		while(a!=b)
    		{
    			if(a>b)
    				n+=a,a>>=1;
    			else
    				n+=b,b>>=1;
    		}
    		n+=a;
    		if(c==1)
    		{
    			write(n),puts("");
    			continue;
    		}
    		ans=0;
    		if(dep(n)<=d)
    			++ans;
    		for(register int l=1;l<=d;++l)
    		{
    			ll k=(2ll<<l)-1;
    			if(k<=n&&dep(n/k)+l<=d)
    				ans+=dfs(l,0,n%k);
    		}
    		for(register int l=1;l<=d;++l)
    			for(register int r=1;r<=d;++r)
    			{
    				ll k=(2ll<<l)+(2ll<<r)-3,b=(1ll<<r)-1;
    				if(k+b<=n&&dep((n-b)/k)+Max(l,r)<=d)
    					ans+=dfs(l-1,r-1,(n-b)%k);
    			}
    		write(ans-1),puts("");
    	}
    	return 0;
    }
    
  • 相关阅读:
    javascript:history.go()和history.back()的区别
    ASP.NET26个性能优化方法
    20 个 jQuery 分页插件和教程,附带实例
    JQuery中$.ajax()方法参数详解
    记住键盘快捷键大全 提高电脑操作速度
    URL重写案例
    url重写(伪静态)IIS配置图解
    URL重写的优缺点分析
    C# GUID的使用
    js中的编码与解码
  • 原文地址:https://www.cnblogs.com/yzhang-rp-inf/p/10933615.html
Copyright © 2011-2022 走看看