我有一个字符串,其大小可以大到“10,000”。我必须计算那些可被9整除的后缀。
SUBSEQUENCE:子序列是一种安排,其中维持给定字符串的顺序。例如:如果给定的字符串是10292,那么它的一些子序列是1,102,10,19,12,12(12是两次2来两次),129,029,09,092等。有些数字不是给定字符串的子序列是:201(2和0不能在1之前),921,0291等。
我试图使用位移生成给定字符串的所有子序列(powerset)并检查每个字符串是否可被9整除。但只要字符串的长度为< = 10,这就可以正常工作。在那之后,我没有得到适当的子序列(一些子序列显示负数)。
以下是我的代码:
scanf("%s", &str); //input string
int n=strlen(str); //find length of string
//loop to generate subsequences
for(i=1;i<(1<<n);++i){
string subseq;
for(j=0;j<n;++j){
if(i&(1<<j)){
subseq+=str[j]; // generate subsequence
}
}
//convert generated subseq to int; number is 'long' tpye
number=atol(subseq.c_str());printf("%ld\n", number);
//ignore 0 and check if number divisible by 9
if(number!=0&&number%9==0)count++;
}
printf("%ld\n", count);
答案 0 :(得分:4)
由于数字可以被9整除,当且仅当其数字的总和可以被9整除时,您可以使用O(n)
递归算法来解决这个问题。
这个想法如下:在每个步骤中,将子序列分成两部分并确定(递归地)有多少个序列的数字总和为i % 9
,其中i
的范围为{{1}到0
。然后,通过以下方式“合并”8
中的两个表,为整个范围构建这个相同的表。假设O(1)
是左侧分割的表格,L
是右侧分割的表格,您需要为整个范围构建表格R
。
然后你有:
F
只有一个数字for (i = 0; i < 9; i++) {
F[i] = L[i] + R[i];
for (j = 0; j < 9; j++) {
if (j <= i)
F[i] += L[j] * R[i - j]
else
F[i] += L[j] * R[9 + i - j]
}
}
的子序列的基本情况很明显:只需将d
和所有其他条目设置为零。
完整的C ++ 11实现:
F[d % 9] = 1
答案 1 :(得分:4)
我有个主意!
由于您只需计算子字符串,因此您并不关心他们实际 的内容。因此,您只需存储可能总和的数量。
然后,如果你有一个可以组合两个子串集的计数表的函数,并给出它们的组合计数怎么办?
既然我知道这是一个可怕的解释,我会举一个例子。说你给了这个号码:
2493
将它分成两半并继续分裂,直到你得到个别数字:
2493
/ \
24 93
/\ /\
2 4 9 3
2
总结为什么?简单:2
。而4
只能汇总到4
。您可以构建有多少子串总和到每个值(mod 9)的表:
0 1 2 3 4 5 6 7 8
2: 0 0 1 0 0 0 0 0 0
4: 0 0 0 0 1 0 0 0 0
9: 1 0 0 0 0 0 0 0 0
3: 0 0 0 1 0 0 0 0 0
组合两个表很容易。添加第一个表,第二个表以及两个mod 9的每个组合(对于第一个组合,这相当于2
,4
和24
;对于第二个, 9
,3
和93
):
0 1 2 3 4 5 6 7 8
24: 0 0 1 0 1 0 1 0 0
93: 1 0 0 2 0 0 0 0 0
然后再做一次:
0 1 2 3 4 5 6 7 8
2493: 3 0 2 2 2 2 2 2 0
您的答案就在0
栏中3
。这对应于子字符串243
,2493
和9
。但是,你不知道,因为你只存储了计数 - 幸运的是,你不在乎!
一旦实施,这将为您提供O(n)
表现 - 您只需要弄清楚如何合并O(1)
中的表格。但是嘿 - 做作业吧?祝你好运!
答案 2 :(得分:0)
如果您使用 int ,那么您不应该将其移位太多。如果这样做,则设置符号位。使用 unsigned int 。或者不要左移太多。如果你坚持 int ,你可以在完成后进行右移。
用于
printf("%ld\n", count);
printf在显示long-int类型时可能会遇到问题。你尝试过cout吗?
答案 3 :(得分:0)
这是根据Akappa算法的C ++代码。然而,该算法对于包含一个或多个0的数字是失败的,即在“10292”和“0189”的情况下,但给出“1292”和“189”的正确答案。如果有人可以调试这个来为所有案例提供答案,我将不胜感激。
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<string>
#include<cstring>
#include<vector>
#include<stack>
#include<sstream>
#include<algorithm>
#include<cctype>
#include<list>
#include<set>
#include<set>
#include<map>
using namespace std;
typedef vector<int> table;
table count(string::iterator beg, string::iterator end)
{
table F(9);
std::fill(F.begin(), F.end(), 0);
if (beg == end)
return F;
if (beg + 1 == end) {
F[(*beg - '0') % 9] = 1;
return F;
}
size_t distance = std::distance(beg, end);
string::iterator mid = beg + (distance / 2);
table L = count(beg, mid);
table R = count(mid, end);
for (unsigned int i = 0; i < 9; i++) {
F[i] = L[i] + R[i];
for(unsigned int j = 0; j < 9; j++) {
if (j <= i)
F[i] += L[j] * R[i - j];
else
F[i] += L[j] * R[9 + i - j];
}
}
return F;
}
table count(std::string s)
{
return count(s.begin(), s.end());
}
int main()
{
cout << count("1234")[0] << endl;
cout << count("12349")[0] << endl;
cout << count("9999")[0] << endl;
cout << count("1292")[0] << endl;cout << count("189")[0] << endl;
cout << count("10292")[0] << endl;cout << count("0189")[0] << endl;
system("pause");
}