UVa1521 GCD Guessing Game(唯一分解定理+素筛)

题目链接

Paul had a birthday yesterday, and they were playing a guessing game there with Andrew: Andrew was trying to guess Paul’s age. Andrew knew that Paul’s age is an integer between 1 and n, inclusive. Andrew can guess any number x between 1 and n, and Paul will tell him what is the greatest common divisor of x and his age. Here’s a possible course of the game for n = 6. Andrew starts with guessing 3, and Paul replies that the greatest common divisor of 3 and his age is 1. That means that Paul’s age can’t be 3 or 6, but can still be 1, 2, 4 or 5. Andrew continues with guessing 2, and Paul replies 2. That means that Paul’s age can’t be 1 or 5, and the only two remaining choices are 2 and 4. Finally, Andrew guesses 4, and Paul replies 2. That means that Paul’s age is 2, and the game is over. Andrew needed three guesses in the above example, but it’s possible to always determine Paul’s age in at most two guesses for n = 6. The optimal strategy for Andrew is: at the first step, guess 6. If Paul says 1, then its 1 or 5 and he can check which one by guessing 5. If Paul says 2, then its 2 or 4,
and he can check by guesing 4 as we’ve seen above. If Paul says 3, then we already know the answer is 3. Finally, if Paul says 6, the answer is 6. What is the number of guesses required in the worst case if Andrew guesses optimally for the given n?

Input
The input will contain several test cases, each of them as described below.
The input file contains one integer n, 2 ≤ n ≤ 10000.

Output
For each test case, write to the output on a line by itself. Output one integer — the number of guesses Andrew will need to make in the worst case.

1.题目大意:给出一个数n,现在让我们猜1~n内的一个数y,唯一的提示是我们没猜一个数x,就会提示gcd(x,y)的值,现在让我们求给定n的最小猜的次数

2.自己做没想出来怎么做。过了一个月想起了补题,便去网上查阅一番。题目并不好懂,来回想了一天多才懂怎么做了。首先根据质因数分解定理,除了1以外任何一个正整数都可以表示成若干个质因数的乘积,那么显然我们一旦猜了一个质数,那么含该质因子的合数都会因为给出的gcd被判断出来是不是在下一个猜的范围内。但是这还不够,不难发现最坏的情况是猜完了所有质数才确定了答案(因为n范围内的质数起码构成了包括n在内的合数,也就是n内的合数分解质因子的范围就在n以内,具体说是sqrt(n+0.5))。那怎么才能更快呢,一次猜多个质数!比如6=2*3,那么我们猜6的时候,因为6含有2和3的质因子,因此答案是否含有2和3就可以确定,如果不含有那么就直接排除了所有含2和3质因子的数。那么如果想更快,就必须排除更多的数,那么问题就变成了n以内的多个质数相乘不超过n就可以被分为一组,也就是判断一次即可,能分成多少组就能判断多少次(当所有质数都判断了n以内的所有数也都判断了)

代码:

#include <iostream>
#include <cstring>
#include <math.h>
using namespace std;
const int maxn=1e4+10;
int prime[maxn];
bool isprime[maxn];
int num,n;

void init(){  //埃氏筛法
    memset(isprime,true,sizeof(isprime));
    num=0;
    for(int i=2;i<maxn;i++){
        if(isprime[i]){
            prime[num++]=i;
            for(int j=i*i;j<maxn;j+=i)
                isprime[j]=false;

        }
    }
}

int main()
{
    ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
    init();
    while(cin>>n){
        int l,r,k=1,ans=0;
        while(prime[k]<=n){  //找最大的小于n的质数的下标
            if(k>=num) break;
            k++;
        }
        l=0,r=k-1;
        while(l<=r){
            int res=prime[r];
            while(prime[l]*res<=n) res*=prime[l++];
            ans++;
            r--;
        }
        cout<<ans<<endl;
    }
    return 0;
}

发布了128 篇原创文章 · 获赞 7 · 访问量 5255

猜你喜欢

转载自blog.csdn.net/qq_44691917/article/details/104703195