一个数末尾有多少个 0,取决于:min(2 的个数, 5 的个数)

我们要找连续子段,使得min(sum2, sum5) == k

等价于sum2 ≥ k 且 sum5 ≥ k并且 min(sum2, sum5) == k

用双指针维护s2[r] - s2[l-1] ≥ k, s5[r] - s5[l-1] ≥ k

#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N = 2e5 + 5;
int n,k; 
int c2[N], c5[N];
int cal(int k){
    int l = 1;
    int res = 0;
    int sum2 = 0, sum5 = 0;
    for (int r = 1; r<=n; r++){
        sum2 += c2[r];
        sum5 += c5[r];
        while (l<=r && sum2 >=k && sum5 >=k){
            sum2 -= c2[l];
            sum5 -= c5[l];
            l++;
        }
        res += (l-1);
    }
    return res;
}
void solve(){
    cin >>n>>k;
    int cnt2 = 0, cnt5 = 0;
    vector<int>a(n + 1);
    for (int i = 1; i<=n; i++) {
        cin >>a[i];
        int x = a[i];
        c2[i] = c5[i] = 0;
        while (x % 2 == 0) c2[i]++, x/=2;
        while (x % 5 == 0) c5[i]++, x/=5;

    }
    cout<<cal(k) - cal(k + 1)<<'\n';
}

signed main(){
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);

    int tt; cin >> tt;
    while (tt--) solve();

    return 0;
}