2022-07-11:給定n位長的數字字串和正數k,求該子符串能被k整除的子串個數。
(n<=1000,k<=100)。
來自微眾。4.11筆試。
答案2022-07-11:
動態規劃。假設abcdef%k=0,abc000%k=0,那麼def%k=0。
程式碼用rust編寫。程式碼如下:
use rand::Rng;
fn main() {
let nn: i64 = 18;
let kk: i64 = 20;
let test_time: i32 = 3000;
println!("測試開始");
for i in 0..test_time {
let str = random_number(rand::thread_rng().gen_range(0, nn) + 1);
let k = rand::thread_rng().gen_range(0, kk) + 1;
let ans1 = mod_ways1(&str, k);
let ans2 = mod_ways2(&str, k);
if ans1 != ans2 {
println!("出錯了!{}", i);
println!("ans1 = {}", ans1);
println!("ans2 = {}", ans2);
break;
}
}
println!("測試結束");
}
// 暴力方法
// 為了驗證
fn mod_ways1(s: &str, k: i64) -> i64 {
let n = s.len() as i64;
let mut ans = 0;
for i in 0..n {
for j in i..n {
if (&s[i as usize..(j + 1) as usize]).parse::<i64>().unwrap() % k == 0 {
ans += 1;
}
}
}
return ans;
}
// 正式方法
// 時間複雜度O(N * k)
fn mod_ways2(s: &str, k: i64) -> i64 {
let mut cur: Vec<i64> = vec![];
for _ in 0..k {
cur.push(0);
}
// 幫忙遷移
let mut next: Vec<i64> = vec![];
for _ in 0..k {
next.push(0);
}
// 0...i 整體餘幾?
let mut mod0: i64 = 0;
// 答案:統計有多少子串的值%k == 0
let mut ans = 0;
for cha in s.bytes() {
for i in 0..k {
// i -> 10個
// (i * 10) % k
next[((i * 10) % k) as usize] += cur[i as usize];
cur[i as usize] = 0;
}
let mut tmp = cur.clone();
cur = next.clone();
next = tmp.clone();
mod0 = (mod0 * 10 + (cha - '0' as u8) as i64) % k;
ans += if mod0 == 0 { 1 } else { 0 } + cur[mod0 as usize];
cur[mod0 as usize] += 1;
}
return ans;
}
// 為了測試
fn random_number(n: i64) -> String {
let mut ans: Vec<u8> = vec![];
for _i in 0..n {
ans.push('0' as u8 + rand::thread_rng().gen_range(0, 10));
}
return String::from_utf8(ans).unwrap();
}
執行結果如下:
本作品採用《CC 協議》,轉載必須註明作者和本文連結