2021hdu多校第五场补题

1006-Cute Tree

题目链接

 

题目大意

根据所给代码  输入一个n 问您最后生成多少个点

题目思路

记忆化搜索

当len=1 时return  当 len=2时生成两个 len=3时生成三个 当len>2时根据他所给公式计算分段

最后别忘了加上自身这个节点 还有分三段的第一段要注意向上取整

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=2e5+10;
int t,n;
ll dp[maxn];
ll dfs(int x)
{
	if(dp[x])return dp[x];
	if(x==3)return dp[3]=4;
	if(x==2)return dp[2]=3;
	if(x==1)return dp[1]=1;
	ll ans=0;
	if(x>3)
	{
		ll tt= (x-1)/3+1;
		ans+=dfs(tt)+dfs((x-tt)/2)+dfs(x-(tt)-(x-tt)/2);
	}
	return dp[x]=ans+1;
}
int main()
{
	cin>>t;
	while(t--)
	{
		cin>>n;
		ll ans=dfs(n);
		int x;
		while(n--)scanf("%d",&x);
		
		cout<<ans<<endl;
	}
	//cout<<dp[3]<<endl;
	//int qq=(10-1)/3+1;
	//cout<<(10-qq)/2<<" "<<10-(qq)-(10-(qq/2))<<endl;
	return 0;
}

1007-Banzhuan

题目链接

题目大意

一个nxnxn的立方体 你要用1x1x1的方块去填他 方块放在(x,y,z)的代价为 v=x*y2*z

你需要让你填的这个物体 从上面 左面 前面看都是nxn的正方形 另外放置方案会保证万有引力

即你放在最上面 下面要是没有东西就会落下来 你要输出满足方案的最大值和最小值

题目思路

对于最小值来说 最下面的一层即z=1是一定会铺满的 因为满足地心引力 且只有铺满才能从上面看 满足nxn正方形 然后只需要考虑如何从左面和从前面看满足nxn

我一开始想的是既然代价是x*y2 那么肯定要让y最大时x最小 而且对于每一层来说 这一层的每一行每一列只需要出现一个方块即可 那么对于每一层可以这样放置

 wa了两发后发现这样根本不是最优!

 

 经思考发现  下面这个才是最优

 

 因此最min的费用就是 最底下一层铺满 和 2-n层如上图放置

表达式为:

minans=左边的一面 + 前面的一面 + 最底下的一层

(\sum_{i=2}^{n}yi^{2})*(\sum_{i=2}^{n}zi) +(\sum_{i=2}^{n}xi^{})*(\sum_{i=2}^{n}zi) +(\sum_{i=1}^{n}yi^{2})*(\sum_{i=1}^{n}xi)

结合公式 1^2+2^2+3^2+…+n^2=n(n+1)(2n+1)/6

最后推出式子大概是(没化简)

 然后考虑max费用 这里有一个坑 就是大多数人会默认觉得 直接全铺满nxnxn个格子 但实际上 由于满足万有引力 正确答案是从z=n这一层开始放 放n次 这样才是最大 费用!

则maxans=最上面一层 x n

(\sum_{i=1}^{n}yi^{2})*(\sum_{i=1}^{n}xi)*n*n

#include<bits/stdc++.h>
#define debug(a,b) printf("%s = %d\n",a,b);
using namespace std;
typedef long long ll;
typedef pair<int, int> PII;
const ll INF_ll=1e18;
const int INF_int=0x3f3f3f3f;
inline ll read(){
   ll s=0,w=1ll;
   char ch=getchar();
   while(ch<'0'||ch>'9'){if(ch=='-')w=-1ll;ch=getchar();}
   while(ch>='0'&&ch<='9') s=s*10ll+((ch-'0')*1ll),ch=getchar();//s=(s<<3)+(s<<1)+(ch^48);
   return s*w;
}
const int mod=1e9+7;
void rd_txt(){
    #ifdef ONLINE_JUDGE
    #else
        freopen("in.txt","r",stdin);
    #endif
}
ll qpow(ll a,ll b)
{
    ll res = 1;
    while(b)
    {
        if(b&1) res = res*a%mod;
        a = a*a%mod;
        b >>= 1;
    }
    return res;
}

void solve(){
    ll n;
    ll ans=0,sum=0;
    scanf("%lld",&n);
    n=n%mod;
    ll t1=(((((((n*(n+1)%mod)*(2*n+1)%mod)%mod)*(qpow(6,mod-2)%mod)%mod))*(((1+n)*n)%mod-1+mod)%mod)%mod)%mod;
    t1=(t1+2)%mod;
	ll t2=(((n*(n+1))%mod )*((n*(n+1))%mod))%mod;
	t2=(t2*(qpow(4,mod-2)%mod))%mod; 
	t2%=mod;
	 ll t3=(((3*(1+n)%mod*n)%mod)*(qpow(2,mod-2))%mod)%mod;
	 ans=(mod+t1+t2-t3)%mod;//最小值 
	 cout<<ans<<endl;
	 ans=(((n*(n+1))%mod*((2*n+1)%mod))%mod*(qpow(6,mod-2))%mod)%mod;
    sum=((((((((ans*n)%mod*(n+1))%mod)*qpow(2,mod-2)%mod)%mod)*n)%mod)*n)%mod;
    
    printf("%lld\n",sum);//最大值 
}
int main()
{
    //rd_txt();
    int t;
    cin>>t;
    while(t--){
        solve();
    }

}
//1000000000000000000

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值