一个数末尾有多少个 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;
}

京公网安备 11010502036488号