HBCPC 2018 网络赛H 【分块】

H. GSS and OJ Submissions
time limit per test
6 seconds
memory limit per test
512 megabytes
input
standard input
output
standard output

GSS is holding a large programming contest on the website called EOJ or compileError Online Judge which is the largest programming contest platform in the world. Every day, millians of codes are submitted to the platform.

One day, someone submitted the n-th code (1 ≤ n ≤ 4 × 108), where n is GSS's lucky number, to celebrate this day, GSS is going to send a huge prize. In this case, he allocated every submission a number in [0, 264) (see the paragraph below), then he generate another number L in [1, n] . The user who submitted the submission with the L-th small number will receive the prize.

GSS allocate numbers to submissions in the following way:

typedef unsigned long long ull;
void allocate(ull A, ull B, ull s0, ull s[])
{
    s[0] = s0;
    for (int i = 1; i < n; i++) {
        s[i] = s[i - 1] * A + B;
    }
}

AB and s0 are generated elsewhere, and 0 ≤ A, B, s0 < 264. And you can assume that A, B and s0 are generated in random.

Special notice: the code above will comsume about 2 seconds or more on judger.

Now, Mingming have collected all numbers allocated to his submissions, and he wants to know weather he will win the prize. But he is too lazy to solve, so he asked you for help, please, tell him the number allocated to the submission which win the prize.

Input

Input contains 5 integers, A, B, L, n, s0.

Output

Output one line with the number —— the number allocated to the submission which win the prize.

Example
input
Copy
5 7 9 11 13
output
Copy
5761717
Note

The numbers allocated to submissions are:

13, 72, 367, 1842, 9217, 46092, 230467, 1152342, 5761717, 28808592, 144042967

it is clear that the ninth one is 5761717.

题意:给4e8个unsigned long long范围内整数,求其第l大数为多少?

分析:4e8个数,利用分块算法将其分成N块,块与块之间存在绝对的大小关系,就能间接的快速比较,然后在块内求出第l大。

#include<bits/stdc++.h>
using namespace std;
typedef unsigned long long LL;
const LL NV=1e14+1;
int num[200010];
LL A,B,s,s0,b[50000];
int n,l,k;
int main()
{
    while(scanf("%llu%llu%d%d%llu",&A,&B,&l,&n,&s)!=EOF)
    {
        for(int i=1;i<=200000;i++)num[i]=0;
        s0=s;
        for(int i=1;i<=n;i++)
        {
            num[s0/NV]++;
            s0=s0*A+B;
        }
        for(int i=0;i<200000;i++)
        {
            if(l>num[i])
                l-=num[i];
            else
            {
                k=i;
                break;
            }
        }
        s0=s;
        int cnt=0;
        for(int i=1;i<=n;i++)
        {
            if(k==s0/NV)
                b[++cnt]=s0;
            s0=s0*A+B;
        }
        sort(b+1,b+cnt+1);
        printf("%I64d\n",b[l]);
    }
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值