当前位置: 首页 > 知识库问答 >
问题:

ADAGAME4 Spoj错误答案

乐正远航
2023-03-14

下面是SPOJ的一个归档问题。示例测试用例通过了,但我在提交时得到了W/A。我缺少一些测试用例(testCase)。需要帮助来找出我错过了什么案例和/或我做错了什么。

瓢虫艾达正在和她的朋友维尼特玩除数游戏。这个游戏有以下规则。他们之间有一堆石头。移动中的玩家可以选择至少1块,最多σ(N)块石头(其中σ(N)代表N的除数)。显然,N在每次移动后都会发生变化。得不到任何石头(N==0)的人输了。

因为瓢虫艾达是个淑女,所以她先动。你能决定谁获胜吗?假设两个玩家都玩得很好。

输入

输入的第一行将包含1≤ T≤ 10^5,测试用例的数量。接下来的T行将包含1≤ N≤ 2*10^7,最初堆放的石块数量。

输出

输出获胜者的名字,所以可以是“Ada”或“Vinit”。

样本输入:
8
1
3
5
6
11
1000001
1000000
29

示例输出:
Ada
Vinit
Ada
Ada
Vinit
Vinit
Ada
Ada

密码

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

}

共有1个答案

宋宏儒
2023-03-14

您的CountDivisors()函数中存在一个微妙的错误。它假定lastPrimeDivisor[num]-如名称所示-

然而,事实并非如此。例如,lastPrimeDivisor[num]=2为所有偶数,或lastPrimeDivisor[7*89]=7。原因是在

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

仅更新从i*i开始的数组元素。

因此,lastPrimeDivisor[num]实际上是num的一些素因子,但不一定是最大的。因此,numof除数[55447]计算为8,而不是正确的值6。

因此,在countDivisors()中,必须通过重复除法明确确定num中素因子的指数。

然后可以使用除数函数是乘法的。这将导致以下实施:

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];
        }
    }
}
 类似资料:
  • 链接到挑战 拉梅什和苏雷什每人在彩票上都会得到一个满满五颗星的盒子。由于两个盒子不需要相同数量的巧克力,他们决定玩游戏。获胜者可以同时拥有两盒巧克力。他们交替玩,苏雷什开始游戏。给定两个盒子中的巧克力数量,让它们成为c1和c2,玩家取c1或c2数量的巧克力,并将剩余的一盒巧克力分成两盒(这两个盒子不需要相同数量的巧克力)。不能做出这种举动的玩家输了。输入 输入的第一行包含一个数字 T(1 (1 输

  • 在一条数字线上有n个位于不同位置的信标。第i个信标具有位置Ai和功率电平Bi。当第i个信标被激活时,它摧毁其左侧(坐标递减方向)距离bi(含)内的所有信标。然而,信标本身并没有被摧毁。埼玉县将从右至左一个一个地启动信标。如果一个信标被破坏,它就不能被激活。 埼玉希望Genos在所有现有信标的右边严格地添加一个信标,具有任何位置和任何功率等级,这样尽可能少的信标被破坏。注意,Genos放置的信标意味

  • 我试着在SPOJ上解决一个问题,我们必须简单地找到给定数组a的最长递增子序列的长度。 我用动态规划O(n^2)算法解决了这个问题,这个解决方案被接受了。。以下是被接受的代码: 但是当我试图用第二种方法(LINK)解决它时,:: ,我得到了错误的答案。 这是我的c代码 我不知道为什么我会得到错误的答案。你能帮我找到这个错误吗。或者站点中给出的基于LCS的LIS算法不正确??

  • 问题内容: 例如,这样简单的事情: 打印110.00000000000001而不是110。使用其他数字代替100 * 1.1还会给出很多数字,并且末尾有一些随机数字,这是不正确的。 有任何想法吗? 问题答案: 浮点符号的准确性有限。这是一个指南:http : //floating-point- gui.de/

  • 问题内容: 以下脚本应返回部门的名称以及这些部门中的雇员人数,市场营销,执行和销售部门的雇员为‘0’,但返回的值为‘1’,而不是‘0’。我该如何纠正? 问题答案: 不要使用数数您想数数的员工。 计算整行。由于在进行计数(*)时,部门中每个部门始终至少会有一个记录,因此您总是会获得至少1条记录 演示

  • 问题内容: 在该问题中,我引用了以下代码: 我在该问题中发现,该结果按model.classes_给出的顺序表示了属于每个类的点的概率 所以…如果正确解释,此答案表示该点可能是“橙色”(由于数据量很少,因此置信度较低)。但是直觉上,这个结果显然是不正确的,因为给出的点与“苹果”的训练数据相同。可以肯定的是,我也进行了相反的测试: 同样,显然是不正确的,但方向相反。 最后,我尝试了更远的点。 同样,