小白赛73 DE
链接:https://ac.nowcoder.com/acm/contest/57683/E
来源:牛客网
来源:牛客网
首先我们得知道0怎么来的,显然根据质因数的原理,0只有从2和5两个质数相乘而来,那么我们只需要记录每个数字的2和5的数量,并且记录2的个数和5的个数的前缀和,二者取最小即为0的个数
然后就是枚举加二分了,枚举区间左界l,二分查找有界,找到最小的和最大的右界r1和r2使得l~r1和l~r2刚好有k个0,答案就加上r2-r1+1
#include<iostream> #include<cstring> #include<algorithm> #include<cmath> using namespace std; long long n,p2[200005],p5[200005]; long long c[200005]; long long a[200005],t,k; int main() { cin >> t; while (t--) { cin >> n >>k; int cnt2=0,cnt5=0; p2[0]=0; p5[0]=0; for(int i =1 ; i<= n ;i++) { cin >> a[i]; int c2=0,c5 =0; int t = a[i]; while(t%2==0) { c2++; t/=2; } t = a[i]; while(t%5==0) { c5++; t/=5; } p2[i]=p2[i-1]+c2; p5[i]=p5[i-1]+c5; } long long ans = 0; for(int l = 1 ; l<= n ;l++)//枚举左界 { int l1 =l ,r =n; while(l1<r)//找符合要求的下界(最小的右界) { int mid =(l1+r)/2; long long t =min((p2[mid]-p2[l-1]),(p5[mid]-p5[l-1])); if(t >= k) r= mid ; else l1 = mid+1; } long long t =min((p2[l1]-p2[l-1]),(p5[l1]-p5[l-1])); if(t!=k) continue; int l2 =l, r2 = n; while(l2<r2)//上界 { int mid = (l2+r2+1)/2; long long t =min((p2[mid]-p2[l-1]),(p5[mid]-p5[l-1])); if(t > k) r2= mid-1 ; else l2 = mid; } t =min((p2[l2]-p2[l-1]),(p5[l2]-p5[l-1])); if(t!=k)continue; ans+=l2-l1+1; } cout<<ans<<endl; } return 0; }