- 可被 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;
}
};