D简单版本的做法(二分):因为0的个数只会越乘越多,故可用前缀积维护,满足二分性,每次枚举左端点,二分右端点,即可计算出答案。
using namespace std;
using ll = long long;
const int N = 2e5 + 5;
ll a[N];
ll T[N];
int n, k;
ll check(ll q) { // 计算后导零
ll res = 0;
while (q && q % 10 == 0) {
res += 1;
q /= 10;
}
return res;
}
void solve() {
cin >> n >> k;
T[0] = 1;
ll ans = 0;
for (int i = 1; i <= n; i++) {
cin >> a[i];
T[i] = T[i - 1] * a[i];
}
for (int l = 1; l <= n; l++) { // 枚举左端点
int tl = l, tr = n;
while (tl < tr) { // 找到最小的右端点
int mid = tl + tr >> 1;
if (check(T[mid] / T[l - 1]) >= k)
tr = mid;
else
tl = mid + 1;
}
int ans1 = tl;
tl = l, tr = n;
while (tl < tr) { // 找到最大的右端点
int mid = tl + tr + 1 >> 1;
if (check(T[mid] / T[l - 1]) <= k)
tl = mid;
else
tr = mid - 1;
}
if (check(T[ans1] / T[l - 1]) == k) // 判断是否找到区间
ans += tl - ans1 + 1;
}
cout << ans << endl;
}
int main(void) {
int m;
cin >> m;
while (m--)
solve();
return 0;
}