GCD Guessing Game Gym

http://codeforces.com/gym/100085/attachments

因为那个数字是一个质数,这样的猜的次数是最多的,所以至少是质数次。

但是如果需要猜2、3,那么可以直接猜6,也能达到猜2和3的效果。

想要猜7、11,那么可以猜77,会产生gcd = 7的有7、49、77,gcd = 11的有11、77

所以相当于把1--n的质数分组,每组的乘积不能超过n,求最小的组数。

#include <bits/stdc++.h>
#define IOS ios::sync_with_stdio(false)
using namespace std;
#define inf (0x3f3f3f3f)
typedef long long int LL;

const int maxn = 1e6 + 20;
int prime[maxn], mu[maxn];//这个记得用int,他保存的是质数,可以不用开maxn那么大
bool check[maxn];
int total;
void initprime() {
    mu[1] = 1; //固定的
    for (int i = 2; i <= maxn - 20; i++) {
        if (!check[i]) { //是质数了
            prime[++total] = i; //只能这样记录,因为后面要用
            mu[i] = -1; //质因数分解个数为奇数
        }
        for (int j = 1; j <= total; j++) { //质数或者合数都进行的
            if (i * prime[j] > maxn - 20) break;
            check[i * prime[j]] = 1;
            if (i % prime[j] == 0) {
                mu[prime[j] * i] = 0;
                break;
            }
            mu[prime[j] * i] = -mu[i];
            //关键,使得它只被最小的质数筛去。例如i等于6的时候。
            //当时的质数只有2,3,5。6和2结合筛去了12,就break了
            //18留下等9的时候,9*2=18筛去
        }
    }
}
vector<int> vc;
bool vis[maxn];
void work() {
    int ans = 0;
    int n;
    scanf("%d", &n);
    for (int i = 1; i <= n; ++i) {
        if (prime[i] > n) break;
        vc.push_back(prime[i]);
    }
    for (int i = 0; i < vc.size(); ++i) {
        if (vis[i]) continue;
        int now = vc[i];
        for (int j = vc.size() - 1; j >= 0; --j) {
            if (vis[j]) continue;
            if (now * vc[j] <= n) {
                vis[j] = true;
                now *= vc[j];
            }
        }
        ans++;
    }
    printf("%d
", ans);
}

int main() {
#ifdef local
    freopen("data.txt", "r", stdin);
//    freopen("data.txt", "w", stdout);
#endif
    freopen("gcd.in", "r", stdin);
    freopen("gcd.out", "w", stdout);
    initprime();
    work();
    return 0;
}
View Code
原文地址:https://www.cnblogs.com/liuweimingcprogram/p/7436226.html