1591 - Data Mining

来源:互联网 发布:怎么跟网络管理员联系 编辑:程序博客网 时间:2024/06/06 09:46

Dr. Tuple is working on the new data-miningapplication for Advanced Commercial Merchandise Inc. One of the subroutines forthis application works with two arrays P and Q containing Nrecordsof data each (records are numbered from 0 to N - 1).Array P contains hash-like structure with keys. Array P isused to locate record for processing and the data for the corresponding recordis later retrieved from the array Q.

All records in array P havea size of SP bytes and records in array Q havesize of SQ bytes. Dr. Tuple needs to implement thissubroutine with the highest possible performance because it is a hot-spot ofthe whole data-mining application. However, SP and SQ areonly known at run-time of application which complicates or makes impossible tomake certain well-known compile-time optimizations.

The straightforward way to find byte-offsetof i-th record in array P is to use the followingformula:

Pofs(i) = SP . i,

(1)

and the following formula for array Q:

Qofs(i) = SQ . i.

(2)

However, multiplication computes much slowerthan addition or subtraction in modern processors. Dr. Tuple avoids usage ofmultiplication while scanning array P by keeping computedbyte-offset Pofs(i) of i-th record instead of itsindex i in all other data-structures of data-miningapplication. He uses the following simple formulae when he needs to computebyte-offset of the record that precedes or follows i-th record inarray P:

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

Pofs(i - 1) = Pofs(i)- SP

Whenever a record from array P islocated by either scanning of the array or by taking Pofs(i)from otherdata structures, Dr. Tuple needs to retrieve information from the correspondingrecord in array Q. To access record in array Q itsbyte-offset Qofs(i) needs to be computed. One can immediatelyderive formula to compute Qofs(i) with known Pofs(i) fromformulae (1) and (2):

Qofs(i) = Pofs(i)/SP . SQ

(3)

Unfortunately, this formula not only containsmultiplication, but also contains division. Even though only integer divisionis required here, it is still an order of magnitude slower than multiplicationon modern processors. If coded this way, its computation is going to consumethe most of CPU time in data-mining application for ACM Inc.

After some research Dr. Tuple has discoveredthat he can replace formula (3) with the following fast formula:

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

(4)

where A and B arenon-negative integer numbers, ``< < A" is left shiftby A bits (equivalent to integer multiplication by 2A), ``> > B" is right shift by B bits(equivalent to integer division by 2B).

This formula is an order of magnitude fasterthan (3) to compute, but it generally cannot always produce the same result as(3) regardless of the choice for values of A and B.It still can be used if one is willing to sacrifice some extra memory.

Conventional layout of array Q inmemory (using formula (2)) requires N . SQ bytesto store the entire array. Dr. Tuple has found that one can always choosesuch K that if he allocates Kbytes of memory forthe array Q (where KN . SQ)and carefully selects values for A and B, the fastformula (4) will give non-overlapping storage locations for each of the N recordsof arrayQ.

Your task is to write a program that findsminimal possible amount of memory K that needs to be allocatedfor array Q when formula (4) is used. Corresponding valuesfor A and B are also to be found. If multiplepairs of values for A and B give the sameminimal amount of memory K, then the pair where A isminimal have to be found, and if there is still several possibilities, the onewhere B is minimal. You shall assume that integer registersthat will be used to compute formula (4) are wide enough so that overflow willnever occur.

Input 

Input consists of several datasets. Eachdataset consists of three integer numbers NSP ,andSQ separated by spaces (1N220, 1SP210, 1SQ210).

Output 

For each dataset, write to the output asingle line with three integer numbers KA, and Bseparated by spaces.

Sample Input 

1024 7 1

Sample Output 

1119 2 5

参考答案代码:

#include<stdio.h>

#include<string.h>

 

long long n, sp,sq;

int A,B;

 

int main()

{

   while(scanf("%d%d%d",&n,&sp,&sq)==3)

    {

        bool firstk = true;

        long long k;

        int kn = 0;

        for(int i = 0; i<=31; i++)

        {

            for(int j = 0; j<= 31; j++)

            {

                long long tempk =(((n-1)*sp+(((n-1)*sp)<<i))>>j)+sq;

                if(tempk<sq*n) break;

                else

                {

                    if(firstk)

                    {

                        k = tempk;

                        A = i;

                        B = j;

                        firstk = false;

                    }

                    else if(k > tempk)

                    {

                        k = tempk;

                        A = i;

                        B = j;

                    }

                }

            }

        }

        printf("%lld %d %d\n", k , A,B);

    }

}

所谓偏移量Pofs(i)其实就是当P数组为连续存储时第i个元素距离P数组起始存储位置的距离。根据原题有如下公式

Pofs(0)=0

Pofs(1)=Pofs(0)+Sp

...

Pofs(i)=Sp*i

同理

Pofq(i)=Sq*i

又因为

i=Pofs(i)/Sp

所以

Pofq(i)=Sq*Pofs(i)/Sp

但是乘法和除法cpu计算起来太慢了所以题目要求用下面这个公式代替上面那个公式来通过Pofs(i)计算Qofs‘(i)

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

题目的要求就是找到最优的A和B使得利用Qofs‘(i)存储Q数组所需的空间K尽量小。多解时取最小A,仍多解取最小B。

因为N*Sq<=2^30所以A/B的取值范围大致确定为[0,32)(其实我是看了测试数据才确认的数据范围...)所以本题比较适合暴力穷举。

同时A/B的取值应使得K>=n*Sq 既 ( ((n-1)*Sp+ (n-1)*Sp < < A) > > B)+Sq>=n*Sq

 

 

没看懂的代码:

#include<iostream>

using namespacestd;

 

int main()

{

    long long n, x, y, N, A, B, ansN, ansA,ansB;

    while (cin >> n >> x >>y)

    {

        ansN = n*y<<10;//有何原因左移10个位???

        for (A = 0; A < 32; A++)

        {

            for (B = 0; B < 32; B++)

            {

                N =(((n-1)*x+((n-1)*x<<A))>>B) + y;

                if (N>=n*y &&N<ansN)

                {

                    ansA = A;

                    ansB = B;

                    ansN = N;

                }

            }

        }

        cout << ansN << "" << ansA << " " << ansB <<"\n";

    }

    return 0;

}

0 0