问题:Topcoder SRM 170 500
考虑序列{x0,x1,x2,...}。根据先前术语定义某个术语xn的关系称为递归关系。线性递归关系是递归形式为xn = c(k-1)* x(n-1)+ c(k-2)* x(n-2)+ ... + c(0 )* x(nk) 其中所有c(i)都是实值常数,k是递归关系的长度,n是任意大于或等于k的正整数。 您将获得一个int []系数,按顺序指示c(0),c(1),...,c(k-1)。您还将获得一个int []初始值,给出x(0),x(1),...,x(k-1)和int N的值。您的方法应返回xN modulo 10。 / p>
更具体地说,如果系数的大小为k,那么递归关系将是 xn =系数[k-1] * xn-1 +系数[k-2] * xn-2 + ... +系数[0] * xn-k。
例如,如果系数= {2,1},初始= {9,7},N = 6,那么我们的递归关系是xn = xn-1 + 2 * xn-2,我们有x0 = 9然后x2 = x1 + 2 * x0 = 7 + 2 * 9 = 25,同样,x3 = 39,x4 = 89,x5 = 167,x6 = 345,所以你的方法会返回(345模数) 10)= 5。
约束: - 代码必须在小于或等于2秒的时间内运行 - 内存利用率不得超过64 MB
我的尝试解决方案:
class RecurrenceRelation
{
public int moduloTen(int[] coefficients, int[] initial, int N)
{
double xn = 0; int j = 0;
int K = coefficients.Length;
List<double> xs = new List<double>(Array.ConvertAll<int, double>(initial,
delegate(int i)
{
return (double)i;
}));
if (N < K)
return negativePositiveMod(xs[N]);
while (xs.Count <= N)
{
for (int i = xs.Count - 1; i >= j; i--)
{
xn += xs[i] * coefficients[K--];
}
K = coefficients.Length;
xs.Add(xn);
xn = 0;
j++;
}
return negativePositiveMod(xs[N]);
}
public int negativePositiveMod(double b)
{
while (b < 0)
{
b += 10;
}
return (int)(b % 10);
}
}
我对这个解决方案的问题是双重表示的精确性,因为我不能在.NET中使用第三方库或BigInteger库用于此SRM,所以我需要找到一种解决方法来解决它。我怀疑我可以使用递归,但我对如何去做有点无能为力。
这是一个测试用例,显示我的代码何时起作用以及何时起作用
{2,1},{9,7},6 - 成功返回5 {9,8,7,6,5,4,3,2,1,0},{1,2,3,4,5,6,7,8,9,10},654 - 未成功返回8而不是5由于双精度的精度
任何人都可以帮我解决这个问题吗?我打算考虑使用数组来存储值,但它有点超出我的特别是如何满足乘法,并且仍然在问题中设置的时间和空间复杂度。也许我的整个方法都错了?我很欣赏一些指示和方向(没有完全充实的答案)答案。
由于
答案 0 :(得分:4)
请注意,我们只需要返回xn
的模10。
我们还需要知道,如果a = b + c
,我们有a % 10 = (b % 10 + c % 10) %10.
a = b*c
,我们也有a % 10 = (b %10 * c % 10) % 10;
所以,对于
xn = c(k-1) * x(n-1) + c(k-2) * x(n-2) + ... + c(0) * x(n-k)
= a0 + a1 + .... + an
(a0 = c(k - 1)* x(n-1),a1 = ......)
我们有xn % 10 = (a0 % 10 + a1 % 10 + ...)%10
对于每个ai = ci*xi
,所以ai % 10 = (ci % 10 * xi % 10)% 10
。
因此,通过所有这些数学计算,我们可以避免使用double并将结果保持在可管理的大小。
答案 1 :(得分:1)
正如Pham所回答的那样,诀窍是要意识到你只需要返回一个模数,从而绕过溢出问题。这是我的快速尝试。我使用一个队列来输入最后一个结果xN,并逐出最旧的结果。
static int solve(int[] coefficients, int[] seed, int n)
{
int k = coefficients.Count();
var queue = new Queue<int>(seed.Reverse().Take(k).Reverse());
for (int i = k; i <= n; i++)
{
var xn = coefficients.Zip(queue, (x, y) => x * y % 10).Sum() % 10;
queue.Enqueue(xn);
queue.Dequeue();
}
return (int) (queue.Last() );
}
编辑: 获得与预期相同的结果,但我不保证此示例中没有错误。