我有一系列数字说1,2,4,0我必须找到可被6整除的序列号。
所以我们将有0,12,24,120,240,这意味着答案将是5,
问题在于我设计了一种算法,该算法需要O(2^n)
时间复杂度,因此基本上它会遍历所有可能的天真。
是否有某种方法可以降低复杂性。
Edit1:允许多个数字副本。例如输入可以是1,2,1,4,3 Edit2:数字应按顺序排列,如上例42 420等不允许
代码:此代码无法考虑120
`#include <stdio.h>
#include<string.h>
#define m 1000000007
int main(void) {
int t;
scanf("%d",&t);
while(t--)
{
char arr[100000];
int r=0,count=0,i,j,k;
scanf("%s",&arr);
int a[100000];
for(i=0;i<strlen(arr);i++)
{
a[i]=arr[i]-'0';
}
for(i=0;i<strlen(arr);i++)
{
for(j=i;j<strlen(arr);j++)
{
if(a[i]==0)
{
count++;
goto label;
}
r=a[i]%6;
for(k=j+1;k<strlen(arr);k++)
{
r=(r*10 + a[k])%6;
if(r==0)
count++;
}
}
label:;
r=0;
}
printf("%d\n",count);
}
return 0;
}
答案 0 :(得分:6)
您可以使用动态编程。
像往常一样,当我们决定使用动态编程解决问题时,我们首先将一些输入值转换为参数,然后添加一些其他参数。
参数的明显候选者是序列的长度。
我们的序列为a[1]
,a[2]
,...
,a[N]
。
因此,我们搜索f(n)
(从n
到0
的{{1}})值N
,a[1]
的子序列数,a[2]
,...
,当作为数字读取时,可被a[n]
整除。
当我们知道D=6
时,计算f(n)
看起来并不明显,所以我们深入研究细节。
仔细看看,我们现在面临的问题是,在数字末尾添加一个数字可以将f(n-1)
整除的数字变为不能被D
整除的数字,反之亦然。
尽管如此,当我们在数字的末尾添加一个数字时,我们确切地知道余数是如何变化的。
如果我们有一个序列D
,p[1]
,p[2]
,...
并且知道p[k]
,那么数字r
模数的其余部分p[1] p[2] ... p[k]
,然后将D
添加到序列中,新号码p[k+1]
模s
的余数p[1] p[2] ... p[k] p[k+1]
很容易计算:D
考虑到这一点,我们可以将余数模数为s = (r * 10 + p[k+1]) mod D
我们的新参数。
因此,我们现在搜索D
(f(n,r)
从n
到0
和N
从r
到0
)是D-1
,a[1]
,a[2]
,...
的子序列数,当读作数字时,余数为a[n]
模r
现在,知道D
,f(n,0)
,f(n,1)
,...
,我们想要计算f(n,D-1)
,f(n+1,0)
,{{1} },f(n+1,1)
。
对于...
,f(n+1,D-1)
,a[1]
,a[2]
的每个可能子序列,当我们考虑元素编号...
时,我们要么为其添加a[n]
,或省略n+1
并保持子序列不变。
这通过前向动态编程而不是公式更容易表达:
a[n+1]
结果a[n+1]
(取决于let f (n + 1, *) = 0
for r = 0, 1, ..., D - 1:
add f (n, r) to f (n + 1, r * 10 + a[n + 1]) // add a[n + 1]
add f (n, r) to f (n + 1, r) // omit a[n + 1]
,是一个或多个术语的总和)是f (n + 1, s)
,s
,{{的子序列数1}},a[1]
,a[2]
产生余数...
modulo a[n]
。
整个解决方案如下:
a[n+1]
我们从答案中减去一个,因为空子序列不被视为数字。
时间和内存要求为s
。
当我们注意到,在每个给定时刻,我们只需要存储D
和let f (0, *) = 0
let f (0, 0) = 1 // there is one empty sequence, and its remainder is 0
for n = 0, 1, ..., N - 1:
let f (n + 1, *) = 0
for r = 0, 1, ..., D - 1:
add f (n, r) to f (n + 1, r * 10 + a[n + 1]) // add a[n + 1]
add f (n, r) to f (n + 1, r) // omit a[n + 1]
answer = f (N, 0) - 1
,我们可以将内存降低到O (N * D)
,因此O (D)
的存储空间可以是{ {1}}代替f (n, *)
。
您的示例序列的插图:
f (n + 1, *)
练习:如何使用此解决方案摆脱前导零的数字? 我们还需要另一个参数吗?