20170319胡策

T1
这里写图片描述
这里写图片描述

没做。
UPD:这道题应当从1维、2维和3维来思考,然后推出n维的计算方法。
证明:(不太正规)
对于任意n-1维的东西,映射到n维上都是一个面。当我们知道n-1维的东西切k-1刀,和n维的东西切k-1刀所得的最大份数,就相当于将在n维的东西在切过k-1刀后选择切第k刀的最佳位置,那么我们可以将第k刀切出的面抽出来,在其中添加第k刀,实际上就是在答案中加上n-1维的东西切k-1刀所得到的答案。
于是我们可以得到递推式:
                 f(n,k)=f(n,k1)+f(n1,k1)
画成表格就是这样:

n\k11111
123456
136101521
1410203556

为了方便我们举个栗子:
这里写图片描述
现在我们在三维的情况下,已经切了三刀,将要切第四刀,我们可以将即将形成的切面抽出来,得到的对答案贡献最大的方案是这样的:
这里写图片描述
所以对答案的最大贡献是7。

T2
这里写图片描述
这里写图片描述
这里写图片描述

这道题好亏啊,一上午的时间都放在这道题上了。好不容易写出一道数位dp,结果和暴力一比较有至少一半输出比正答大了1。
UPD:这道题如果用数位dp只能得30分,其余的会T掉,正解应该是树形dp,详细可以参考这个文档

这是我考场上写的代码:(又臭又长)
我这份代码有点小问题,很多时候输出的答案比正确答案大1。

#include<cstdio>
#include<iostream>
using namespace std;
typedef unsigned long long ull;
ull T,l,r,m,ans;
ull f[20];
int num[20];
inline void divide(ull n)
{
    int pos=0;
    while(n) num[++pos]=n%10,n/=10;
}
inline ull numlen(ull n)
{
    int ans=0;
    while(n) ans++,n/=10;
    return ans;
}
inline ull getkpre(ull n,ull wh)
{
    ull s=1;
    while(s!=wh) n/=10,s++;
    return n;
}
inline ull getten(ull k)
{
    if(!k) return 1;
    ull ans=10,s=1;
    while(s!=k) ans*=10,s++;
    return ans;
}
inline ull eachsum(ull n)
{
    ull ans=0;
    while(n) ans+=n%10,n/=10;
    return ans;
}
inline ull work(ull n)
{
    ull ans=0,len=numlen(n);
    divide(n);
    for(ull i=1;i<len;i++)
      ans+=f[i];
    for(int i=1;i<num[len];i++)
      ans+=f[len-1]+i*getten(len-1);
    for(int i=len;i>1;i--)
      for(int j=0;j<num[i-1];j++)
      {
        ans+=(eachsum(getkpre(n,i))+j)*getten(i-2);
        if(i-2>0) ans+=f[i-2];
      }
    ans+=eachsum(n);
    return ans;
}
inline bool getneed(int l,int r,int &end)
{
    ull L=l,R=r,mid,tmp1,tmp2=work(l-1);
    while(L<R)
    {
        mid=(L+R)>>1;
        tmp1=work(mid);
        if(tmp1-tmp2>=m) R=mid;
        else L=mid+1;
    }
    if(work(L)-tmp2>=m)
    {
        end=L+1;
        return 1;
    }
    return 0;
}
inline ull solve()
{
    int L=l,R=r,ans=0;
    while(getneed(L,R,L))
    {
        ans++;
        if(L>=R) break;
    }
    return ans;
}
int main()
{
    freopen("B.in","r",stdin);
    freopen("B.out","w",stdout);
    cin>>T;
    f[1]=45;
    for(int i=2;i<=19;i++)
      f[i]=45*getten(i-1)+10*f[i-1];
    while(T--)
    {
        cin>>l>>r>>m;
        cout<<solve()<<endl;
    }
    fclose(stdin);fclose(stdout);
    return 0;
}

T3

这里写图片描述
这里写图片描述
没做。
UPD:这道题应当把长方体中的每一层分别抽出来,然后进行计算。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值