mayoko’s diary

プロコンとかいろいろ。

SRM 672 div1 easy:Procrastination

解法

n 以上で最小の素数を p1, n 未満で最大の素数を p2 とすると, 実は n 番目の task を持っている人は p2 より大きく p1 以下の番号の人に絞られます。これは, 任意の素数 p に対して p と p+1 の swap が起きないことから明らかです。

ということで, p1〜p2-1 の約数を全列挙してシミュレーションしましょう。素数は 1/log n の確率で現れるので, p2-p1 はまぁ 500 くらいで抑えられ, それらの約数がすべて O(sqrt(n)) だけあったとしてもシミュレーションは十分間に合います。

const ll INF = 1ll<<55;

bool prime(ll n) {
    for (ll i = 2; i*i <= n; i++) if (n%i == 0) return false;
    return true;
}

class Procrastination {
public:
    long long findFinalAssignee(long long n) {
        // n 以上の素数を探す
        ll up = n;
        while (!prime(up)) up++;
        // n 未満最大の素数を探す
        ll lp = n-1;
        while (!prime(lp)) lp--;
        // lp+1 ~ up の約数を列挙
        vector<ll> divs;
        for (ll i = lp+1; i <= up; i++) {
            for (ll j = 2; j*j <= i; j++) if (i%j == 0) {
                divs.push_back(j);
                divs.push_back(i/j);
            }
        }
        sort(divs.begin(), divs.end());
        divs.erase(unique(divs.begin(), divs.end()), divs.end());
        for (ll el : divs) {
            if ((n-1)%el == 0) n--;
            else if (n%el == 0) n++;
        }
        return n;
    }