【发布时间】:2017-12-15 13:38:11
【问题描述】:
以下是来自 SPOJ 的存档 PROBLEM。示例 testCase 正在通过,但我在提交时收到了 W/A。我缺少一些测试用例(测试用例)。需要帮助来弄清楚我遗漏了什么案例和/或我在这里做错了什么。
Ada the Ladybug 正在与她的朋友 Velvet Mite Vinit 玩除数游戏。游戏有以下规则。它们之间有一堆N块石头。正在移动的玩家可以选择至少 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
样本输出:
艾达
维尼特
艾达
艾达
维尼特
维尼特
艾达
阿达
代码
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;
}
}
}
【问题讨论】:
-
(嗯。此处未启用 MathJax。)105 和 107 是指 10^5 和 10^7 吗?
标签: java algorithm dynamic-programming memoization