链接:登录—专业IT笔试面试备考平台_牛客网
来源:牛客网
题目描述 :
宝乐很喜欢末尾数位上是0的数字,如果一个数末尾至少有k个0我们就称其为完美数。现在有一个长度为n的数组,如果一个子区间的所有数字之积是完美数,那么我们就称该区间为完美区间。宝乐想知道该数组有多少完美区间,聪明的你帮忙解决这个问题吧。
本题子区间的定义:原始序列或集合中的一段连续的子集,其中元素之间的顺序保持不变。
输入描述:
输入一行两个整数n,k,分别代表数组大小和完美数末尾的0的个数。
接下来一行包含 n 个整数 ai。1<=n<=2*10^5 1<=k<=2*10^6 1<=ai<=1*10^9 。
输出描述:
输出一行一个正整数,表示完美区间的个数。
分析:由题目的数据范围可以看出暴力枚举和二层循环会超时,需要进行一定的剪枝处理,看题可以得出末尾有0的数可以看成是n个2和n个5相乘,那么我们就可以把这n个数分为2个数组,一个数组用来存放2,一个数组用来存放5,然后用前缀和处理2个数组,求出前n项和有多少个2,有多少个5,然后遍历n个数,取这两个数组中的最小值,当这两个数组最小值大于等于k时,那么它后面的数也一定含有k个0,所以直接将后面的个数相加即可,最后输出总数。
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=2*1e5+5;
int a1[N],a[N],b[N],sum1[N],sum2[N],sum;//a1存放n个数
void check(int x,int i)
{
int t=x;
while(t%2==0){
t/=2;
a[i]++;//a数组存入2
}
t=x;
while(t%5==0){
t/=5;
b[i]++;//b数组存入5
}
}
signed main(){
ios::sync_with_stdio(false);
int n,k;
cin >> n >> k;
for(int i=1;i<=n;++i){
cin >> a1[i];
check(a1[i],i);//i用来标记下标
}
for(int i=1;i<=n;++i)
{
sum1[i]=sum1[i-1]+a[i];//前缀和处理
sum2[i]=sum2[i-1]+b[i];
}
for(int i=0;i<=n;++i)
for(int j=i+1;j<=n;++j)
{
int t1=sum1[j]-sum1[i];
int t2=sum2[j]-sum2[i];
int minn=min(t1,t2);//取2和5个数的最小值,最小值即为末尾有几个0
if(minn>=k)
{
sum+=n-j+1;//将后面的数累加
break;
}
}
cout << sum << endl;
return 0;
}