紫书——Data Mining UVA - 1591

版权声明: https://blog.csdn.net/a673953508/article/details/81326065

题目大意:

这题估计没多少人愿意做,题目太难懂了(我放弃了几次orz)

先了解题意:

首先P(i)和Q(i)我们要将他了解为偏移量,就是离开始数组p【0】啊等等的距离,而他们每个字节就是Sp和Sq;

这就很好理解第一二条公式了

Pofs(i) = SP · i      就是P【i】离P【0】的距离,也可以理解为数组P有i个元素的大小

Qofs(i) = SQ · i.     这个和上面同理

Pofs(i + 1) = Pofs(i) + SP

Pofs(i − 1) = Pofs(i) − SP

这两条公式也很容易从上面两条推导出来,多一个就是多sp嘛

又因为 

i = Pofs(i)/SP   =》 Qofs(i) = Pofs(i)/SP · SQ

上面的公式其实没用,但是要将他理解为通过 P 定位出 Q的数据 (重点!!!!)

但是由于除法和乘法太慢了,所以博士用空间转换为时间,得出下面公式

Qofs’(i) = (Pofs(i) + Pofs(i)<<A) >> B

这条公式也是通过P定位Q的资料位置,好比映射位置一样,学过汇编都应该知道就像中断向量表一样,最后加上一个Q的大小就等于全部Q的大小了

但是现在Q已经不是连续的了,中间可能有些位置是没有资料的,所以我们要找最小的数组大小K;

K相同就找A小的,A相同就找B小的,一分析就知道枚举A、B就行了

而由于N*Sq最大范围为 2^30 (不超过int),所以我们可以将A、B分别枚举到35

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int inf = 0x3f3f3f3f;

int main()
{
    ll n,p,q;

    while(scanf("%lld%lld%lld",&n,&p,&q) == 3) {
        ll k = (ll)inf*3;
        int a,b;
        for(int i = 0; i < 35; i++) {
            for(int j = 0; j < 35; j++) {
                ll tmp = (((n-1)*p + ((n-1)*p<<i))>>j) + q;
                if(tmp >= n*q && k > tmp) {
                    k = tmp;
                    a = i;  b = j;
                }
            }
        }
        printf("%lld %d %d\n",k,a,b);
    }

    return 0;
}

猜你喜欢

转载自blog.csdn.net/a673953508/article/details/81326065