[英]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.