可被 5 整除的二进制前缀

给定由若干 0 0 0 1 1 1 组成的数组 A A A。我们定义 N i N_i Ni:从 A [ 0 ] A[0] A[0] A [ i ] A[i] A[i] 的第 i i i 个子数组被解释为一个二进制数(从最高有效位到最低有效位)。

返回布尔值列表 a n s w e r answer answer,只有当 N i N_i Ni 可以被 5 5 5 整除时,答案 a n s w e r [ i ] answer[i] answer[i]true,否则为 false

示例 1:

输入:[0,1,1]
输出:[true,false,false]

解释:
输入数字为 0 0 0, 01 01 01, 011 011 011;也就是十进制中的 0 0 0, 1 1 1, 3 3 3 。只有第一个数可以被 5 5 5 整除,因此 a n s w e r [ 0 ] answer[0] answer[0] 为真。
示例 2:

输入:[1,1,1]
输出:[false,false,false]

示例 3:

输入:[0,1,1,1,1,1]
输出:[true,false,false,false,true,false]

示例 4:

输入:[1,1,1,0,1]
输出:[false,false,false,false,false]

提示:

1 < = A . l e n g t h < = 30000 1 <= A.length <= 30000 1<=A.length<=30000
A [ i ] A[i] A[i] 0 0 0 1 1 1

N i N_i Ni为数组 A A A 从下标 0 0 0 到下标 i i i 的前缀表示的二进制数,则有 N 0 = A [ 0 ] N_0=A[0] N0=A[0] i > 0 i>0 i>0 时,有 N i = N i − 1 × 2 + A [ i ] N_i=N_{i-1} \times 2+A[i] Ni=Ni1×2+A[i]。令 n n n 为数组 A A A 的长度,则对于 0 ≤ i < n 0 ≤ i < n 0 \le i<n0≤i<n 0i<n0i<n,可以依次计算每个 N i N_i Ni的值。对于每个 N i N_i Ni的值,判断其是否可以被 5 5 5 整除,即可得到答案。

考虑到数组 A A A 可能很长,如果每次都保留 N i N_i Ni的值,则可能导致溢出。由于只需要知道每个 N i N_i Ni是否可以被 5 5 5 整除,因此在计算过程中只需要保留余数即可。

M i M_i Mi表示计算到下标 i i i 时的除以 5 5 5 的余数,则有 M 0 = A [ 0 ] M_0=A[0] M0=A[0](显然 A [ 0 ] A[0] A[0] 一定小于 5 5 5),当 i > 0 i>0 i>0 时,有 M i = ( M i − 1 × 2 + A [ i ] )   m o d   5 M_i=(M_{i-1} \times 2+A[i])\bmod 5 Mi=(Mi1×2+A[i])mod5,判断每个 M i M_i Mi是否为 0 0 0 即可。由于 M i M_i Mi一定小于 5 5 5,因此不会溢出。

如何证明判断 M i M_i Mi是否为 0 0 0 可以得到正确的结果?可以通过数学归纳法证明。

i = 0 i=0 i=0时,由于 $N_0=A[0]<5,因此 M 0 = N 0 M_0=N_0 M0=N0, M 0 = N 0   m o d   5 M_0=N_0\bmod 5 M0=N0mod5成立。

i > 0 i>0 i>0 时,假设 M i − 1 = N i − 1   m o d   5 M_{i-1}=N_{i-1}\bmod 5 Mi1=Ni1mod5成立,考虑 N i   m o d   5 N_i\bmod 5 Nimod5 M i M_i Mi
的值:
N i   m o d   5 = ( N i − 1 × 2 + A [ i ] )   m o d   5 = ( N i − 1 × 2 )   m o d   5 + A [ i ]   m o d   5 M i = ( M i − 1 × 2 + A [ i ] )   m o d   5 = ( N i − 1   m o d   5 × 2 + A [ i ] )   m o d   5 = ( N i − 1   m o d   5 × 2 )   m o d   5 + A [ i ]   m o d   5 = ( N i − 1 × 2 )   m o d   5 + A [ i ]   m o d   5 \begin{aligned} N_i\bmod 5=&(N_{i-1} \times 2+A[i])\bmod 5 \\ =&(N_{i-1} \times 2)\bmod 5+A[i]\bmod 5 \\ \\ M_i=&(M_{i-1} \times 2+A[i])\bmod 5 \\ =&(N_{i-1}\bmod 5 \times 2+A[i])\bmod 5 \\ =&(N_{i-1}\bmod 5 \times 2)\bmod 5+A[i]\bmod 5 \\ =&(N_{i-1} \times 2)\bmod 5+A[i]\bmod 5 \end{aligned} Nimod5==Mi====(Ni1×2+A[i])mod5(Ni1×2)mod5+A[i]mod5(Mi1×2+A[i])mod5(Ni1mod5×2+A[i])mod5(Ni1mod5×2)mod5+A[i]mod5(Ni1×2)mod5+A[i]mod5

即可得到正确的结果。

class Solution {
public:
    vector<bool> prefixesDivBy5(vector<int>& A) {
        int n=A.size();
        vector<bool>res;
        int num=0;
        for (int i=0;i<n;i++){
            num=(num*2+A[i])%5;
            if (num==0){
                res.push_back(true);
            }else res.push_back(false);
        }
        return res;
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值