赞
踩
因为结尾0的个数取决于有多少对 ( 2 , 5 ) (2,5) (2,5) 相乘,那么对于下面例题,解题思路为:
1、将每个数字中的2和5剥离出来,然后用两个数组进行记录,然后其子数 ( 2 , 5 ) (2,5) (2,5)组成对至少为k个。
2、遍历每一个子数组然后计算:会发现超时:
下面公式推导一下:
t
o
t
l
e
2
−
t
w
o
>
=
k
、
t
o
t
l
e
5
−
f
i
v
e
>
=
k
由于
t
w
o
=
f
2
[
j
]
−
f
2
[
i
]
;
这里的
f
为数组
2
剥离的前缀和
由于
f
i
v
e
=
f
5
[
j
]
−
f
5
[
i
]
;
上述
i
,
j
为子数组
(
i
,
j
−
1
)
。因此我们固定
i
,由于前缀和是递增的,因此可以使用二分,找到右边界。
推到出:
t
o
t
l
e
−
(
f
[
j
]
−
f
[
i
]
)
>
=
k
;
t
o
t
l
e
+
f
[
i
]
−
k
>
=
f
[
j
]
;
totle2-two>=k、totle5-five>=k\\ 由于two = f2[j]-f2[i];这里的f为数组2剥离的前缀和\\ 由于five = f5[j]-f5[i];\\ 上述i,j 为子数组(i,j-1)。因此我们固定i,由于前缀和是递增的,因此可以使用二分,找到右边界。\\ 推到出: totle-(f[j]-f[i])>=k;\\ totle+f[i]-k>=f[j];
totle2−two>=k、totle5−five>=k由于two=f2[j]−f2[i];这里的f为数组2剥离的前缀和由于five=f5[j]−f5[i];上述i,j为子数组(i,j−1)。因此我们固定i,由于前缀和是递增的,因此可以使用二分,找到右边界。推到出:totle−(f[j]−f[i])>=k;totle+f[i]−k>=f[j];
那么讨论一下边界问题:
二分 f [ j ] f[j] f[j]返回的是第一个大于 f [ j ] f[j] f[j]值的位置,但是这时就不符合 t o t l e + f [ i ] − k > = f [ j ] totle+f[i]-k>=f[j] totle+f[i]−k>=f[j]了,因此减去1,此时是刚好的。
#include <iostream> #include <set> #include <vector> using namespace std; // 剥离n中存在几个base的因子。如果是2,和5的话, // 就是base中存在多少个2相乘和多少个5相乘 int factor(int n, int base){ int ans = 0; while (n and !(n%base)) { n/=base; ans++; } return ans; } int base_right(const vector<int>& vec, int value){ int left = 0; int right = vec.size()-1; int res = -1; while (left<=right) { int mid = left+((right-left)>>1); if(vec[mid]>value){ res = mid; right = mid-1; }else{ left = mid+1; } } if(res == -1) return vec.size(); return res; } int main() { int n, k; cin>>n>>k; vector<int> vec(n); vector<int> factor2(n+1); vector<int> factor5(n+1); int totle2 = 0; int totle5 = 0; for(int i=0;i<n;i++){ cin>>vec[i]; int x = factor(vec[i], 2); factor2[i+1] = factor2[i]+x; totle2+=x; x = factor(vec[i], 5); factor5[i+1] = factor5[i]+x; totle5+=x; } // 这里进行二分查找加速 long long ans = 0; for(int i=0;i<n;i++){ // 以每个点为起点 int val2 = totle2+factor2[i]-k; int val5 = totle5+factor5[i]-k; int pos2 = base_right(factor2, val2); int pos5 = base_right(factor5, val5); if(min(pos2, pos5)-i-1<=0) continue; ans+=min(pos2, pos5)-i-1; } cout<<ans<<endl; return 0; }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。