Problem:
MathJax.Hub.Config({
tex2jax: { inlineMath: [['\\(','\\)']] }
});

Problem F: MLE

ICPC World Finals 4日目

暗い嵐の夜だった。 夢の中でティー氏はタイムスリップしていた。
ICPCの会場のようだが何かおかしい…。 もしや…これは、N年前（Nは自然数）のICPCなのか…? 混乱の内に競技は開始してしまった。
だが慌てる必要はない。 きっと問題も簡単に違いない。 例えばこれなどはソートするだけで解けてしまうはずではないか。
冷静にコードを書き上げ、速やかにSubmit。

しかしその結果は…Memory Limit Exceeded…?!

問題

C++言語については以下のコード

long long int a[n];
unsigned long long int x = x0;
for (int i = 0; i < n; i++) {
a[i]=(long long int)x;
x ^= x << 13;
x ^= x >> 7;
x ^= x << 17;
}

Java言語については以下のコード

long[] a = new long[n];
long x = x0;
for(int i = 0; i < n; i++){
a[i] = x;
x ^= x << 13;
x ^= x >>> 7;
x ^= x << 17;
}

で与えられる擬似乱数列\( a[0], a[1], \cdots, a[n-1] \)を昇順にソートする。 \(k\)番目の数（\(
a[k-1] \)）を答えよ。

入力

n k x0

1行目に 擬似乱数列の長さ\(n\)、 求めるインデックス\(k\)、 コード中の初期値\(x0\) が空白区切りで与えられる。

出力

問題文にて定義された擬似乱数列において\(k\)番目に小さい数を1行に出力せよ。

制約

\( 0 \leq x0 \leq 9 \)

\( 1 \leq n \leq 10^{8}(= 100000000) \)

\( 1 \leq k \leq n \)

入出力例

入力1

20 10 1

出力1

-768720241707614171

この入力において生成される数列は以下の通りである。

1
1082269761
1152992998833853505
-7269227409276787159
-768720241707614171
-8787613929710185883
-670945072575735807
-6753709453369041295
-4166779903597258483
9024654201992055039
8332670729032836398
2074683623940568804
-1176172910426220663
5632491372296299238
-8006175397324373085
-8536891001451786268
-3486562341448986757
1956468987595729445
-6260278484400246991
1076885984028793263

入力2

1000000 100 2

出力2

-9221458681145860019

入力3

100000000 10000000 3

出力3

-7379326796154077070

Solution in C (judge verdict: Runtime Error)

#include <stdio.h>
#include <stdlib.h>

long long getNextRansu(long long x) {
	unsigned long long xx=x;
	xx^=xx<<13;
	xx^=xx>>7;
	xx^=xx<<17;
	return (long long)xx;
}

int qsort_comp_ll(const void* x,const void* y) {
	long long a=*((const long long*)x);
	long long b=*((const long long*)y);
	if(a>b)return 1;
	if(a<b)return -1;
	return 0;
}

int bunpu[262144];

int ransuListNum;
long long ransuList[1000]; /* based on an experiment */

int getBunpuID(long long x) {
	return (int)(x/70368744177664ll)+131072;
}

long long getLowerBound(int id) {
	if(id<131072)return ((id-1)-131072)*70368744177664ll;
	if(id==131072)return -70368744177663ll;
	return (id-131072)*70368744177664ll;
}

long long getUpperBound(int id) {
	if(id<131072)return (id-131072)*70368744177664ll;
	return ((id+1)-131072)*70368744177664ll;
}

int main(void) {
	int n,k,x0;
	long long x;
	int i;
	int now;
	int offset;
	long long lowerBound,upperBound;
	scanf("%d%d%d",&n,&k,&x0);
	if(k==0) {
		puts("0");
		return 0;
	}
	x=x0;
	for(i=0;i<n;i++) {
		bunpu[getBunpuID(x)]++;
		x=getNextRansu(x);
	}
	offset=now=0;
	for(i=0;i<262144;i++) {
		now+=bunpu[i];
		if(now>=k) {
			lowerBound=getLowerBound(i);
			upperBound=getUpperBound(i);
			break;
		}
		offset=now;
	}
	x=x0;
	ransuListNum=0;
	for(i=0;i<n;i++) {
		if(lowerBound<=x && x<upperBound) {
			ransuList[ransuListNum++]=x;
		}
		x=getNextRansu(x);
	}
	qsort(ransuList,ransuListNum,sizeof(ransuList[0]),qsort_comp_ll);
	printf("%lld\n",ransuList[k-offset-1]);
	return 0;
}