小美拿到了一个大小为n的数组,她希望删除一个区间后,使得剩余所有元素的乘积末尾至少有k个 0。小美想知道,一共有多少种不同的删除方案?
输入例子:
5 2
2 5 3 4 20
输出例子:
4
例子说明:
第一个方案,删除[3]。
第二个方案,删除[4]。
第三个方案,删除[3,4]。
第四个方案,删除[2]。
const rl = require("readline").createInterface({ input: process.stdin });
var iter = rl[Symbol.asyncIterator]();
const readline = async () => (await iter.next()).value;
void (async function () {
// Write your code here
let params = [];
while ((line = await readline())) {
let tokens = line.split(" ");
// let a = parseInt(tokens[0]);
// let b = parseInt(tokens[1]);
// console.log(a + b);
params.push(tokens);
}
// console.log(params)
let [n, k] = params[0].map(Number);
let arr = params[1].map(Number);
// console.log(n, k, arr);
// 总的删除可能次数
// let total = ((n + 1) * n) / 2;
// 0的个数 由 2 和 5 的个数决定 统计删除空间2和5的个数
function counterFactor(num, factor) {
let count = 0;
while (num % factor == 0) {
count++;
num /= factor;
}
return count;
}
let prefix2 = Array.from({ length: n + 1 }).fill(0);
let prefix5 = Array.from({ length: n + 1 }).fill(0);
for (let i = 0; i < arr.length; i++) {
prefix2[i + 1] = prefix2[i] + counterFactor(arr[i], 2);
prefix5[i + 1] = prefix5[i] + counterFactor(arr[i], 5);
}
let count = 0;
// 滑动窗口计算
function check(l, r) {
let remaining2 = prefix2[n] - prefix2[r + 1] + prefix2[l];
let remaining5 = prefix5[n] - prefix5[r + 1] + prefix5[l];
return Math.min(remaining2, remaining5) >= k;
}
for (let l = 0; l < n; l++) {
// for(let r=l;r<n;r++){
// 如果当前区间
// if(Math.min(remaining2,remaining5)>=k){
// count++
// }
// }
// 通过二分查找查找到下一个满足的点
let found = -1;
let left = l;
let right = n - 1;
// 找到第一个满足条件的
while (left <= right) {
let mid = Math.floor((left + right) / 2);
if (check(l, mid)) {
left = mid + 1;
found = mid;
} else {
right = mid - 1;
}
}
if (found != -1) {
count += found - l + 1;
}
}
console.log(count);
})();