LeetCode 1015. 可被 K 整除的最小整数--数学证明+取模运算

  1. 可被 K 整除的最小整数

给定正整数 K,你需要找出可以被 K 整除的、仅包含数字 1 的最小正整数 N。

返回 N 的长度。如果不存在这样的 N,就返回 -1。

示例 1:

输入:1
输出:1
解释:最小的答案是 N = 1,其长度为 1。

示例 2:

输入:2
输出:-1
解释:不存在可被 2 整除的正整数 N 。

示例 3:

输入:3
输出:3
解释:最小的答案是 N = 111,其长度为 3。

提示:

1 <= K <= 10^5

题解:
先处理一个问题,题目是要求找111…类型的数字,使得能被K整除,返回长度,于是有

int ans=1,len=1;
while(ans%K!=0)
{
	ans*=10;
	ans+=1;
	len++;
}
return len;

但是这样ans就轻易超出int范围,于是我们可以这样取模运算。

int ans=1,len=1;
while(ans%K!=0)
{
	ans%=K;
	ans*=10;
	ans+=1;
	len++;
}
return len;

这样可以处理超内存问题,但是这样会不会陷入死循环?于是我们利用数学进行一定证明,假设A=1111…,B=111…,A>B。
如果出现死循环,必然会存在这样的A和B,使得
A%K==B%K,并且结果不为0,也就是出现循环节,但是中间没有0的结果,于是陷入无限死循环,继续证明有
A = B + x * K;
A-B = x * K;
K = ( A - B ) / x;
我们的x为整数,A-B也为整数,而且K也为整数,那么来考虑下K存在哪些结果,这些结果就是会陷入死循环,A=1111…,B=111…,A>B,那么A-B=1…00000的类型,比如A=1111,B=11,A-B=1100,因为A>B,所以A-B可以看成A-B=C * (10 ^ p),其中C=111…的形式,p为10的指数,表示末尾0的数目,那么就是K=C * (10^p)/x;于是K有比较小的几种结果为10/x的整数结果,有1,2,5,10,其中1不存在,因为A!=B,有2,5,剩下的10和其他所有的整数结果都是2和5的整数倍,于是我们可以证明知道,但凡K为2或5的倍数,一定会死循环,所以做特判,剩下的进行反复取模运算处理。

AC代码

class Solution {
public:
    int smallestRepunitDivByK(int K) {
        if(K%2==0||K%5==0)return -1;
        int ans=1,len=1;
        while(ans%K!=0)
        {
            ans%=K;
            ans*=10;
            ans+=1;
            len++;
        }
        return len;
    }
};

LeetCode 1015. 可被 K 整除的最小整数--数学证明+取模运算_第1张图片

你可能感兴趣的:(LeetCode,数论,思维题,算法,leetcode,c++)