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; } }
A, B 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 contains 5 integers, A, B, L, n, s0.
Output one line with the number —— the number allocated to the submission which win the prize.
5 7 9 11 13
5761717
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;
}