简体   繁体   English

ADAGAME4 Spoj错误答案

[英]ADAGAME4 Spoj Wrong Answer

Below is a Archive PROBLEM from SPOJ. 以下是SPOJ的存档问题 Sample testCase is passing, but I am getting W/A on submission. 示例testCase通过了,但是提交时我得到了W / A。 I am missing some testCase(testCases). 我缺少一些testCase(testCases)。 Need help to figure out what case I am missing and/or what I am doing wrong here. 需要帮助找出我想念的情况和/或我做错了什么。

Ada the Ladybug is playing Game of Divisors against her friend Velvet Mite Vinit. 瓢虫Ada与她的朋友Velvet Mite Vinit进行除数游戏。 The game has following rules. 该游戏具有以下规则。 There is a pile of N stones between them. 它们之间有一堆N块石头。 The player who's on move can pick at least 1 an at most σ(N) stones (where σ(N) stands for number of divisors of N). 移动中的玩家最多可以选择至少1个σ(N)石头(其中σ(N)代表N的除数)。 Obviously, N changes after each move. 显然,N在每次移动后都会发生变化。 The one who won't get any stones (N == 0) loses. 一无所获(N == 0)的人输了。

As Ada the Ladybug is a lady, so she moves first. 由于瓢虫艾达(Ada)是一位女士,所以她先走了。 Can you decide who will be the winner? 您能决定谁将成为赢家吗? Assume that both players play optimally. 假设两个玩家都发挥最佳。

Input 输入

The first line of input will contain 1 ≤ T ≤ 10^5, the number of test-cases. 输入的第一行将包含1≤T≤10 ^ 5(测试用例的数量)。 The next T lines will contain 1 ≤ N ≤ 2*10^7, the number of stones which are initially in pile. 接下来的T线将包含1≤N≤2 * 10 ^ 7,这是最初堆积的石头数量。

Output 产量

Output the name of winner, so either "Ada" or "Vinit". 输出优胜者的名字,所以是“ Ada”或“ Vinit”。

Sample Input: 输入样例:
8 8
1 1
3 3
5
6 6
11 11
1000001 1000001
1000000 百万
29 29

Sample Output: 样本输出:
Ada 阿达
Vinit VINIT
Ada 阿达
Ada 阿达
Vinit VINIT
Vinit VINIT
Ada 阿达
Ada 阿达

CODE

import java.io.*;

public class Main
{
    public static int max_size = 2 * (int)Math.pow(10,7) + 1;
    //public static int max_size = 25;
    //public static int max_size = 2 * (int)Math.pow(10,6) + 1;
    public static boolean[] dp = new boolean[max_size];
    public static int[] lastPrimeDivisor = new int[max_size];
    public static int[] numOfDivisors = new int[max_size];
    public static void main(String[] args) throws IOException
    {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        preprocess();

        int t = Integer.parseInt(br.readLine());
        while(t > 0)
        {
            int n = Integer.parseInt(br.readLine());
            if(dp[n] == true)
                System.out.println("Ada");
            else
                System.out.println("Vinit");
            t--;
        }
    }
    public static void markLastPrimeDivisor()
    {
        for(int i = 0 ; i < max_size ; i++)
        {
            lastPrimeDivisor[i] = 1;
        }
        for(int i = 2 ; i < max_size ; i += 2)
        {
            lastPrimeDivisor[i] = 2;
        }
        int o = (int)Math.sqrt(max_size);
        for(int i = 3 ; i < max_size; i++)
        {
            if(lastPrimeDivisor[i] != 1)
            {
                continue;
            }
            lastPrimeDivisor[i] = i;
            if(i <= o)
            {
                for(int j = i * i ; j < max_size ; j += 2 * i)
                {
                    lastPrimeDivisor[j] = i;
                }
            }
        }
        /*for(int i = 1 ; i < max_size ; i++)
            System.out.println("last prime of " + i + " is " + lastPrimeDivisor[i]);*/
    }

    public static void countDivisors(int num)
    {
        int original = num;
        int result = 1;
        int currDivisorCount = 1;
        int currDivisor = lastPrimeDivisor[num];
        int nextDivisor;
        while(currDivisor != 1)
        {
            num = num / currDivisor;
            nextDivisor = lastPrimeDivisor[num];
            if(nextDivisor == currDivisor)
            {
                currDivisorCount++;
            }
            else
            {
                result = result * (currDivisorCount + 1);
                currDivisorCount = 1;
                currDivisor = nextDivisor;
            }
        }
        if(num != 1)
        {
            result = result * (currDivisorCount + 1);
        }
        //System.out.println("result for num : " + original + ", " + result);
        numOfDivisors[original] = result;
    }

    public static void countAllDivisors()
    {
        markLastPrimeDivisor();
        for(int i = 2 ; i < max_size ; i++)
        {
            countDivisors(i);
            //System.out.println("num of divisors of " + i + " = " + numOfDivisors[i]);
        }
    }


    public static void preprocess()
    {
        countAllDivisors();
        dp[0] = dp[1] = dp[2] = true;
        for(int i = 3 ; i < max_size ; i++)
        {
            int flag = 0;
            int limit = numOfDivisors[i];
             //If for any i - j, we get false,for playing optimally
            //the current opponent will choose to take j stones out of the
            //pile as for i - j stones, the other player is not winning.
            for(int j = 1 ; j <= limit; j++)
            {
                if(dp[i - j] == false)
                {
                    dp[i] = true;
                    flag  = 1;
                    break;
                }
            }
            if(flag == 0)
                dp[i] = false;
        }

    }

}

There is a subtle bug in your countDivisors() function. countDivisors()函数中有一个细微的错误。 It assumes that lastPrimeDivisor[num] – as the name indicates – returns the largest prime factor of the given argument. 它假定lastPrimeDivisor[num] (如名称所示)返回给定参数的最大素数。

However, that is not the case. 但是,事实并非如此。 For example, lastPrimeDivisor[num] = 2 for all even numbers, or lastPrimeDivisor[7 * 89] = 7 . 例如,对于所有偶数, lastPrimeDivisor[num] = 2 ,或者lastPrimeDivisor[7 * 89] = 7 The reason is that in 原因是

public static void markLastPrimeDivisor()
{
    // ...
    for(int i = 3 ; i < max_size; i++)
    {
        // ...
        if(i <= o)
        {
            for(int j = i * i ; j < max_size ; j += 2 * i)
            {
                lastPrimeDivisor[j] = i;
            }
        }
    }
}

only array elements starting at i * i are updated. 仅更新从i * i开始的数组元素。

So lastPrimeDivisor[num] is in fact some prime divisor of num , but not necessarily the largest. 因此, lastPrimeDivisor[num]实际上是num 一些主要除数,但不一定是最大的。 As a consequence, numOfDivisors[55447] is computed as 8 instead of the correct value 6. 结果, numOfDivisors[55447]被计算为8而不是正确的值6。

Therefore in countDivisors() , the exponent of a prime factor in num must be determined explicitly by repeated division. 因此,在countDivisors() ,必须通过重复除法来明确确定num质数因子的指数。

Then you can use that the divisors function is multiplicative. 然后,您可以使用除数函数是乘法的。 This leads to the following implementation: 这导致以下实现:

public static void countAllDivisors() {

    // Fill the `somePrimeDivisor` array:
    computePrimeDivisors();

    numOfDivisors[1] = 1;
    for (int num = 2 ; num < max_size ; num++) {
        int divisor = somePrimeDivisor[num];
        if (divisor == num) {
            // `num` is a prime
            numOfDivisors[num] = 2;
        } else {
            int n = num / divisor;
            int count = 1;
            while (n % divisor == 0) {
                count++;
                n /= divisor;
            }
            // `divisor^count` contributes to `count + 1` in the number of divisors,
            // now use multiplicative property:
            numOfDivisors[num] = (count + 1) * numOfDivisors[n];
        }
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM