В принципе такого эффекта несложно достичь, применив к последовательности от 0 до 2**48-1 обратимую функцию, дающую хорошее перемешивание (в криптографическом смысле этого слова). Тут уже предложили взять какой-нибудь блочный шифр. Это в общем-то правильная идея, только это а) сложно б) еще надо найти блочный шифр с блоком в 48 бит.

Но можно сделать и проще. Я бы предложил такой вариант.
typedef unsigned __int64 u64;
u64 seed=0;
u64 GetNextNumber() {
u64 v= seed++;
for (int i=0; i<4; i++)
v = ((v^(v>>40)) * 0xA9C839464437) & (1<<48)-1;
return v;
}
Идея тут такая, что умножение хорошо подмешивает младшие биты к старшим, а сдвиг вправо подмешивает старшие биты к младшим. Число взято от балды, важно только, что оно нечетное. Поскольку все операции обратимы, получаемая последовательность должна быть перестановкой чисел от 0 до 2**48-1.