給定n = 1至10^5,以十進制格式存儲爲字符串。例如:如果n = 968,則在所有子序列中,即9,6,8,96,68,98,968中有3個子序列,即968,96和8,其可被8.因此,答案是3.查找n位數的子序列數,可以被8整除
由於答案可能非常大,請打印答案模(10^9 + 7)。
給定n = 1至10^5,以十進制格式存儲爲字符串。例如:如果n = 968,則在所有子序列中,即9,6,8,96,68,98,968中有3個子序列,即968,96和8,其可被8.因此,答案是3.查找n位數的子序列數,可以被8整除
由於答案可能非常大,請打印答案模(10^9 + 7)。
這不是一個代碼寫作服務,所以我只是給你足夠的時間去做。
子序列可以有10種可能的狀態。第一種是空的。第二個是有一個領先的0.而其他8個是一個正在進行的數字是0-7 mod 8.你從字符串的開頭開始,有1種空的方式,沒有辦法做任何事情。在字符串的末尾,您的答案是具有前導0的方式的數量加上正在進行的0數字8的數字。
轉換表應該是顯而易見的。其餘的只是正常的動態編程。
您可以使用動態編程。令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)
個狀態,每個狀態都有2個轉換)。注意:如果數字不能有前導零,則可以只有一個參數指向該狀態:一個標誌,指示子序列的第一個元素是否爲零(該序列不應該擴展)。解決方案的其餘部分保持不變。
這將是子序列,而不是子串+1妥善解決 –
注意:此答案假定您的意思是連續的子序列。
的整除規則爲一個數字,以通過8
整除是如果該號碼最後三個數字爲整除8.利用這一點,能夠獲得簡單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
from 0
to 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
,424968
,1424968
)注意,一些小的修改,將需要考慮長度超過三個數字較小的數字。
因此序列總數= 2 + 4 + 5 = 11
。總複雜度= O(n)
其中n
是位數。
是,利用整除規則使不是檢查單個子序列的任何「天真」的方法,這很容易會是 – Lagerbaer
人們可以使用任何三位數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)
。
你到目前爲止嘗試過什麼?它有一個動態編程標籤。你有關於國家和轉型可能的想法嗎? – kraskevich
如果字符串是'88',那麼答案是什麼?是3(8,8再次88)還是2(只計8次)? – kraskevich
難道真[亞](https://en.wikipedia.org/wiki/Subsequence),或子?在'2 ^(10^5)'子序列,這是相當多... –