给定n = 1到10 ^ 5,以十进制格式存储为字符串。
示例:如果n = 968,则在所有子序列中,即9,6,8,96,68,98,968中,有3个子序列,即968,96和8,可被8整除所以答案是3。
由于答案可能非常大,请打印答案模(10 ^ 9 + 7)。
答案 0 :(得分:2)
您可以使用动态编程。设f(len, sum)
为长度为len
的前缀的子序列数,使其总和为sum
模8(sum
的范围为0到7)。
f
len = 1
的值很明显。过渡如下:
我们可以在新位置开始一个新的子序列:f(len, a[i] % 8) += 1
。
我们可以从较短的前缀继续任何子序列:
for old_sum = 0..7
f(len, (old_sum * 10 + a[i]) % 8) += f(len - 1, old_sum) // take the new element
f(len, old_sum) += f(len - 1, old_sum) // ignore the new element
当然,您可以执行所有计算模块10 ^ 9 + 7并使用标准整数类型。
f(n, 0)
(所有元素都被考虑在内,模8的总和为0)。此解决方案的时间复杂度为O(n)
(因为有O(n)
个状态,每个状态有两个转换。)
注意:如果数字不能有前导零,那么你可以再添加一个参数:一个标志,指示子序列的第一个元素是否为零(这个序列永远不应该被扩展)。其余解决方案保持不变。
答案 1 :(得分:2)
注意:此答案假定您的意思是连续的子序列。
可以被8
整除的数字的可分性规则是该数字的最后三位数是否可被8整除。使用此算法,可以获得{{1}的简单O(n)
算法}是数字中的位数。
n
为N=a_0a_1...a_(n-1)
的十进制代表,数字为N
。n
s = 0
,检查该数字是否可被a_i a_(i+1) a_(i+2)
整除。如果是,请将8
添加到序列数中,即i + 1
。这是因为s = s + i
的所有字符串a_k..a_(i+2)
都可以被8
整除,范围为k
。0..i
到i
循环0
并继续。因此,如果您有n-2-1
,则可分割的子序列位于:
1424968
(i=1
产生424
个数字:i+1 = 2
和424
)1424
(i=3
产生496
个数字:i+1 = 4
,496
,2496
,42496
)142496
(i=4
产生968
个数字:i+1 = 5
,968
,4968
,24968
,{{1} })请注意,需要进行一些小的修改,以考虑长度小于三位的数字。
因此序列总数= 424968
。总复杂度= 1424968
,其中2 + 4 + 5 = 11
是位数。
答案 2 :(得分:0)
这不是代码编写服务,所以我会给你足够的信息。
子序列可以有10种可能的状态。第一种是空的。第二个是有一个领先的0.而另外8个是一个正在进行的数字,它是0-7 mod 8.你从字符串的开头开始,有1种方式是空的,没有办法成为别的东西。在字符串的末尾,您的答案是前导0加上正在进行的数字为0 mod 8的方式的数量。
过渡表应该是显而易见的。其余的只是正常的动态编程。
答案 3 :(得分:0)
可以使用以下事实:对于任何三位数abc
,以下内容为:
abc % 8 = ((ab % 8) * 10 + c) % 8
或换句话说:具有固定起始索引的数字的测试可以级联:
int div8(String s){
int total = 0, mod = 0;
for(int i = 0; i < s.length(); i++)
{
mod = (mod * 10 + s.charAt(i) - '0') % 8
if(mod == 0)
total++;
}
return total;
}
但是我们没有固定的开始指数! 嗯,这很容易解决:
假设有两个序列a
和b
,int(a) % 8 = int(b) % 8
和b
的后缀是a
。无论序列如何继续,a
和b
的模数将始终保持相等。因此,足以跟踪共享具有等值8的属性的序列的数量。
final int RESULTMOD = 1000000000 + 7;
int div8(String s){
int total = 0;
//modtable[i] is the number of subsequences with int(sequence) % 8 = i
int[] modTable = new int[8];
for(int i = 0; i < s.length(); i++){
int[] nextTable = new int[8];
//transform table from last loop-run (shared modulo)
for(int j = 0; j < 8; j++){
nextTable[(j * 10 + s.charAt(i) - '0') % 8] = modTable[j] % RESULTMOD;
}
//add the sequence that starts at this index to the appropriate bucket
nextTable[(s.charAt(i) - '0') % 8]++;
//add the count of all sequences with int(sequence) % 8 = 0 to the result
total += nextTable[0];
total %= RESULTMOD;
//table for next run
modTable = nextTable;
}
return total;
}
运行时为O(n)
。