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; }