На прошлой неделе я участвовал в 1-м раунде кубка Facebook Hacker.
Одной из проблем была в основном проблема Иосифа
Я изучал проблему Иосифараньше, как дискретная математическая задача, поэтому я в основном понимаю, как получить повторение:
f(n,k) = (f(n-1,k) + k) mod n, with f(1,k) = 0
Но это не сработало в Facebook Hacker Cup, потому что максимальное значение n было 10 ^ 12.Значение mak k было 10 ^ 4.
В Википедии упоминается подход, когда k мало, а n велико.В основном удаляют людей из одного раунда, а затем перенумеровывают.Но он не очень описан, и я не понимаю, почему работает перенумерация.
Я посмотрел пример рабочего исходного кода для решения, но я все еще не понимаю эту последнюю часть.
long long joseph (long long n,long long k) {
if (n==1LL) return 0LL;
if (k==1LL) return n-1LL;
if (k>n) return (joseph(n-1LL,k)+k)%n;
long long cnt=n/k;
long long res=joseph(n-cnt,k);
res-=n%k;
if (res<0LL) res+=n;
else res+=res/(k-1LL);
return res;
}
Часть, которую я действительно не понимаю, начинается с res-=n%k
(и последующих строк).Как вы узнали, что так можно скорректировать результат?
Может ли кто-нибудь показать причины, по которым это получается?Или ссылка, которая выводит это?(Я не нашел никакой информации на форумах UVA или topcoder)