vj组队赛--质数的亲儿子题

G - Goodbye

题目链接
“Goodbye to the friends I’ve had, goodbye to my upstairs neighbor, goodbye to the kids downstairs, and anybody who lend me a favor.”

“Or, goodbye to the positive proper divisor?”

That game is popular these days. Two player take turns to choose a specific number and claim it. The player who takes the first turn chooses one positive proper divisor of given n. In the next rounds, player should choose one positive proper divisor (真因数) of the number claimed in the previous round. The player who can’t make a choice will win.

Formally, a positive proper divisor of n is a divisor of n, and it cannot be either 1 or n.

Now Chino is going to play this game with David. Chino always wants to win and meanwhile she wants to keep the chosen number as big as possible. If with the given n, Chino will win directly or fail anyway, you should also tell her.

Can you help Chino to choose her answer in the first round?

Input
The first line contains one integer T (1≤T≤103)denoting the count of testcases.

For each testcase, one line with one integer n (1≤n≤105)
denoting the given n in one game.

Output
For each testcase, you should output the biggest choice, or 0 when Chino will win directly, or −1 when Chino will fail anyway.

Input

4
3
4
8
666

Output

0
-1
4
111

题目大意:a和b两个人玩游戏,a给了我们钱(大雾)所以我们要让a赢。给一个数字,两个人轮流取这个数的真因数(不能包含1和这个数本身),谁不能取了谁就赢。(a先取)

样例解释:3这个数字没有真因数,所以a没法取,a直接获胜,输出0。4这个数字的真因数只有2,所以a取2,然后轮到b取,2这个数字没有真因数,所以b没法取了,b获胜输出-1。8这个数字,a先取4,然后b取2,然后a没法取了,a获胜。(如果a获胜的开局有多个就输出数字最大的那一个),666这个数字,a先取111,然后b只能取3或者37,这两个数字都没有真因数,所以a获胜。

解题思路:其实归根到底就是看到最后的那个数字是不是质数,如果谁先取到质数谁就输了,因为下一个人一定没办法再取了,所以我们尽量要让b取到质数(谁让我们收a的黑钱了呢)。

首先我们假设b最后取的质数是k,那么这个k应该是所给数字n的最大质因子,为什么呢?
1.我们要让b取质数,2.我们要让a开局取得数字尽量大,这样一来如果b取得的是最大质因子,那么就可以保证上面两种情况.
我们再看666那个例子,到最后b只能从111中取真因数,而111这个数字的真因数只有37和3,所以b只能取质数。同理我们可以让a选的那个数字是两个质数相乘的形式,这样一来b只能从两个质数里面选,不管他选什么,他都是输定了,而37刚好是666的最大质因数,没错!这就是关键,a所选的那个数字=一个质数×所给数字n的最大质因数。那么这”一个质数“怎么求呢,题目说了要让a取的数字尽量大,所以我们也要让这”一个质数“尽量大,同时我们需要满足n%(一个质数*n的最大质因数)=0,也就是说你a取得数字得是n的真因数。另外如果数字n一开始就是质数的话直接输出0(a必赢),如果数字n是质数×质数的形式的话直接输出-1(a必输,因为我们就是用这种方法对付b的)。

AC代码:

#include <bits/stdc++.h>

using namespace std;
bool is_prime[100010];
bool factor[100010];
int p,book[100010];
void prime(int n)//从1-n的素数表
{
    int i,j;
    memset(factor,true,sizeof(factor));
    factor[0]=factor[1]=false;
    for(i=2; i<=n; i++)
    {
        if(factor[i])
            book[p++]=i;
        for(j=0; j<p&&book[j]*i<=n; j++)
        {
            factor[book[j]*i]=false;
            if(i%book[j]==0)
                break;
        }
    }
}

int GetMax(int a)//求数字a的最大质因子
{
    if(a==1)
        return 1;
    else
    {
        for(int i=2; i*i<=a; i++)
        {
            if(a%i==0)
            {
                return GetMax(a/i)>GetMax(i)?GetMax(a/i):GetMax(i);
            }
        }
        return a;
    }
}

bool check(int n)//判断数字n是不是质数×质数的形式
{
    int i;
    for(i=2; i<=sqrt(n); i++)
        if(n%i==0)
            if(factor[i]&&factor[n/i])
                return true;
    return false;
}

int main()
{
    int t,n,i;
    scanf("%d",&t);
    prime(100010);//处理素数表
    while(t--)
    {
        scanf("%d",&n);
        if(GetMax(n)==n)//如果一个数字的最大素数因子是他本身,那么他就是个素数
            printf("0\n");
        else if(check(n))
            printf("-1\n");
        else
        {
            for(i=n/GetMax(n); i>=2; i--)//倒着找,从大到小找,找到满足条件的直接break
                if(factor[i]&&n%(i*GetMax(n))==0)
                {
                    printf("%d\n",i*GetMax(n));
                    break;
                }
        }
    }
    return 0;
}

这题真的是质数的亲儿子,用到了很多质数的知识:素数表(素数的快速判定)、求一个数的最大质因子、判断一个数是不是质数×质数的形式……

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值