Uva1591 DataMining

这题是真正意义上的折磨题,属实是给我做吐了。不过也暴露出自身的很多问题来,比如英语阅读能力不足,读了很多遍都没有读懂题,又或者是思维深度不够,没有将内存大小与题中公式结合起来。还有就是总是粗心大意,一遇到问题就用ultra compare去debug,而不是自己去思考。总是遗漏题目中的很多隐藏条件,在这题栽跟头之后,我彻底意识到算法竞赛训练是一个长期的过程,应当舍弃功利心,虚心学习,才能有所提高·。也正如刘汝佳老师所说,此题有着一定的实际意义,不仅是知识上的,也是精神上的。

原题:

简要分析:

题中主要给了两个公式:Pofs(i+1) = Pofs(i)+Sp

Qofs(i) = (Pofs+(Pofs<<A))>>B(左移运算符优先级比加号低,注意加括号)

其中,Pofs与Qofs都为偏移量,所谓偏移量,其实就是元素首地址大小,其中第0号元素首地址大小为0,也就是Pofs(0)=Qofs(0)=0.我们的任务是通过该式计算出Q存储N个元素所需最小内存K大小,。有公式K=Qofs(N-1)+Sq=(Pofs(N-1)+(Pofs(N-1)<<A))>>B+Sq. (Pofs(N-1)=Sp*(N-1))

该公式的实际意义是Q数组第N-1个元素的首地址加上Q数组单个元素存储的bit数,

同时,K>=Sq*N。

接下来,我们大致估算一下A,B的取值范围。long long是64位整数,假设极端情况N取2^20,Sp取2^10,则A,B取32也能完全遍历。

思路就已经很清晰了,枚举A,B求最小K值,K值相同时,A,B尽量小。我选择用一个结构体数组去储存算得的K以及此时的A,B。最后使用传入functor的sort对数组按题目要求排序即可。

代码:

#include<iostream>
#include<algorithm>
#include<cstring>//memset函数
#pragma GCC optimistic(2)
using namespace std;
struct ANS
{
    long long ans;
    int A,B;
};
struct cmp
{
    bool operator ()(const ANS A,const ANS B) const
    {
        if(A.ans!=B.ans)
        {
            return A.ans<B.ans;
        }
        else if(A.A!=B.A)
        {
            return A.A<B.A;
        }
        else
        {
            return A.B<B.B;
        }
    }
};
int main(void)
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    long long N,Sp,Sq;
    while(cin>>N>>Sp>>Sq)
    {
        ANS store[4000];
        memset(store,0,sizeof(store));
        int n=0;
        long long MIN=N*Sq;
        long long Pofs=Sp*(N-1);
        for(int A=0;A<=32;A++)
        {
            for(int B=0;B<=32;B++)
            {
                long long ans=((Pofs+(Pofs<<A))>>B)+Sq;
                if(ans>=MIN)
                {
                    store[n].ans=ans;
                    store[n].A=A;
                    store[n].B=B;
                    n++;
                }
            }
        }
        sort(store,store+n,cmp());
        cout<<store[0].ans<<" "<<store[0].A<<" "<<store[0].B<<endl;
    }
    return 0;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值