版权声明: 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;
}