А еще, конечно, не мозговыносящий алгоритм, но уже интереснее...

Код AS3:
package tests
{
import flash.display.Sprite;
/**
* ...
* @author wvxvw
*/
public class ProbabilityTest extends Sprite
{
private const _variants:Vector.<uint> =
new <uint>[0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
private const _weights:Vector.<uint> =
new <uint>[1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
private var _sum:uint = 10;
public function ProbabilityTest()
{
super();
// position: 0 total: 67
// position: 1 total: 107
// position: 2 total: 105
// position: 3 total: 113
// position: 4 total: 108
// position: 5 total: 88
// position: 6 total: 91
// position: 7 total: 107
// position: 8 total: 115
// position: 9 total: 99
this.testDistribution();
// exclude 5 from the pool completely
this.setChance(5, 0);
// 1,2,3,4,5,5,6,7,8,9
// position: 0 total: 110
// position: 1 total: 120
// position: 2 total: 107
// position: 3 total: 117
// position: 4 total: 117
// position: 5 total: 0
// position: 6 total: 97
// position: 7 total: 115
// position: 8 total: 108
// position: 9 total: 109
this.testDistribution();
// double the chaces for 6
this.setChance(6, 2);
// 1,2,3,4,5,5,7,8,9,10
// position: 0 total: 110
// position: 1 total: 107
// position: 2 total: 106
// position: 3 total: 105
// position: 4 total: 88
// position: 5 total: 0
// position: 6 total: 205
// position: 7 total: 85
// position: 8 total: 93
// position: 9 total: 101
this.testDistribution();
}
public function setChance(of:uint, to:uint):void
{
of = of % 10;
this._sum = this.updateIndices(of, to - this.weightAt(of));
}
private function weightAt(index:uint):uint
{
var previous:uint;
if (index) previous = this._weights[index - 1];
return this._weights[index] - previous;
}
private function updateIndices(from:uint, by:int):uint
{
while (from < 10) this._weights[from++] += by;
return this._sum + by;
}
private function testDistribution():void
{
var results:Vector.<uint> = new Vector.<uint>(10);
var i:int;
for (i = 0; i < 1e3; i++)
{
results[this.selectRandom()]++;
}
for (i = 0; i < 10; i++)
{
trace("position:", i, "total:", results[i]);
}
}
private function selectRandom():uint
{
var random:uint = this._sum * Math.random();
var index:uint = 4;
if (this._weights[index] <= random)
{
while (index < 10)
{
if (this._weights[index++] > random)
{
index--;
break;
}
}
}
else
{
while (index)
{
if (this._weights[--index] <= random)
{
index++;
break;
}
}
}
return index;
}
}
}
Добавлено через 4 минуты
ЗЫ. Не обязательно двоичное дерево, но тоже вариант. Можно предугадать позицию, если, например, мы знаем, что на каждый "шанс" у нас приходится по, скажем, 2 деления, то, тогда, если рандом выдал 8, то это значит, что это должно быть где-то в районе 4-го элемента. Ну или хотябы просто считать не с начала, а с середины, в таком случае наш самый худший случай будет в 2 раза меньше, чем если мы всегда будем считать от начала.
EDIT: Да, а еще можно было бы находить предполагаемый участок, куда упал рандомальный выбор по типу как в quicksort, т.е. делить оставшийся диапазон на 2 все время... хм... ну, вечером наверн сделаю
