【 POI2011 R2 Day0 】保险箱 Strongbox

很新颖的一道题

首先容易发现如果一个数 \(g\) 在答案集合中,那么 \([0,g,2g,3g...]\) 均都在答案集合中

那我们就可以根据 \(m_k\) 来先缩小一下答案 \(g\) 的范围

即:\(g\ | \gcd(m_k,n)\)

其次根据其他的 \(m_i\) ,我们又可以再得到一些限制

即:\(g\ \nmid \gcd(m_i,n)\)

\(ls=gcd(m_k,n)\)

我们可以处理出 \(ls\) 的所有因子

对于每个 \(m_i\) ,我们令 \(ks=gcd(m_i,ls)\)

也就是说所有 \(ks\) 的因子都不满足条件

其次如果该值已经被删过了,那么直接退出就好了

Code
#include <bits/stdc++.h>
#define re register
#define int long long
#define lls long long
#define fr first
#define sc second
#define pb push_back
using namespace std;
const int mol = 1e9 + 7;
const int maxn = 1e7 + 10;
const int INF = 1e9 + 10;
inline int qpow(int a, int b) {
    int ans = 1;
    while (b) {
        if (b & 1)
            (ans *= a) %= mol;
        (a *= a) %= mol;
        b >>= 1;
    }
    return ans;
}
inline int read() {
    int w = 1, s = 0;
    char ch = getchar();
    while (ch < '0' || ch > '9') {
        if (ch == '-')
            w = -1;
        ch = getchar();
    }
    while (ch >= '0' && ch <= '9') {
        s = s * 10 + ch - '0';
        ch = getchar();
    }
    return s * w;
}

set<int> s;
int n, m, a[maxn], p[maxn], cnt;
inline void del(int x) {
    if (s.find(x) == s.end())
        return;
    s.erase(x);
    for (re int i = 1; i <= cnt; i++)
        if (x % p[i] == 0)
            del(x / p[i]);
}
signed main(void) {
    freopen("b.in", "r", stdin);
    freopen("b.out", "w", stdout);
    n = read(), m = read();
    for (re int i = 1; i <= m; i++) a[i] = read();
    int ls = __gcd(n, a[m]), ks = ls;
    for (re int i = 2; i <= sqrt(ls); i++) {
        if (ls % i == 0)
            p[++cnt] = i;
        while (ls % i == 0) ls /= i;
    }
    if (ls != 1)
        p[++cnt] = ls;
    for (re int i = 1; i <= sqrt(ks); i++)
        if (ks % i == 0) {
            s.insert(i);
            if (i * i != ks)
                s.insert(ks / i);
        }
    for (re int i = 1; i < m; i++) del(__gcd(ks, a[i]));
    printf("%lld\n", n / *s.begin());
}

posted @ 2021-11-17 17:06  zJx-Lm  阅读(96)  评论(0编辑  收藏  举报