← 返回题目页

A1628 投票

标程

// A1628 投票 —— 最小质因子判定
//
// 每轮 n 个投票者各投一票,得票最多的候选人留下;人数只会减少,最终停在某个集合上。
// 若停在 k >= 2 个候选人上且永远不变,就是死循环。
//
// 死循环的必要充分条件:存在 k | n 且 2 <= k <= m。
//   充分性:把 n 票平均分给 k 个候选人(每人 n/k 票),其余候选人 0 票,
//           这一轮后恰好剩下这 k 个;此后每轮它们平分 n 票,谁也淘汰不了谁。
//   必要性:死循环时剩下的 k 个候选人每轮都并列最多,即每轮都分到同样的票数,
//           也就是每轮都把 n 票平分,故 k | n;且 k >= 2、k <= m。
//
// 于是「能否死循环」= n 是否存在一个 >= 2 且 <= m 的因子,
// 等价于:n 的最小质因子 spf(n) <= m 时可能死循环(输出 NO),否则一定结束(输出 YES)。
// n = 1 时 spf 视为无穷大,答案恒为 YES。
//
// 实现:小的 n 用线性筛预处理最小质因子(O(1) 查询);
//       大的 n(<= 1e12)用质数试除。

#include <bits/stdc++.h>
using namespace std;

typedef long long ll;

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    int T;
    cin >> T;
    vector<pair<ll, ll>> q(T);
    ll maxN = 1;
    for (auto &e : q) {
        cin >> e.first >> e.second;
        maxN = max(maxN, e.first);
    }

    const int LIM = 10000000;
    int lim = (int)min<ll>(maxN, LIM);
    vector<int> spf(lim + 1, 0);
    vector<int> primes;
    for (int i = 2; i <= lim; i++) {
        if (spf[i] == 0) {
            spf[i] = i;
            primes.push_back(i);
        }
        for (int p : primes) {
            if (1LL * i * p > lim) break;
            spf[i * p] = p;
            if (p == spf[i]) break;
        }
    }

    auto smallestFactor = [&](ll x) -> ll {
        if (x <= 1) return LLONG_MAX; // 没有 >= 2 的因子
        if (x <= lim) return spf[(int)x];
        for (int p : primes) {
            if (1LL * p * p > x) break;
            if (x % p == 0) return p;
        }
        return x; // x 是质数
    };

    for (auto &e : q) {
        ll n = e.first, m = e.second;
        ll p = smallestFactor(n);
        cout << (p <= m ? "NO" : "YES") << '\n';
    }
    return 0;
}

动画演示