2022-11-22 LeetCode 878.第N个神奇的数字 【寻找循环节】

传送门: 第N个神奇的数字 – 困难

题目:

一个正整数如果能被 a 或 b 整除,那么它是神奇的。

给定三个整数 n , a , b ,返回第 n 个神奇的数字。因为答案可能很大,所以返回答案 对 10^9 + 7 取模 后的值。

输入输出示例:

示例 1:

输入:n = 1, a = 2, b = 3
输出:2

示例 2:

输入:n = 4, a = 2, b = 3
输出:6

数据范围:

  • 1 < = n < = 1 0 9 1<=n<=10^9 1<=n<=109
  • 2 < = a , b < = 4 ∗ 1 0 4 2<=a,b<=4*10^4 2<=a,b<=4104

解题思路:

手动模拟几个样例之后,会发现每当到达 a a a b b b 的最小公倍数的倍数时, a a a b b b 各会产生 l c m ( a , b ) a \frac {lcm(a,b)}{a} alcm(a,b) l c m ( a , b ) b \frac {lcm(a,b)}{b} blcm(a,b) 个不同的数,唯独 l c m ( a , b ) lcm(a,b) lcm(a,b) 是 相同的,这样就能找到一个循环节,找到循环节之后,剩下的事情就是进行简单的计算和判断即可。

AC代码:

class Solution {
public:
    long long mo = 1e9 + 7;
    int nthMagicalNumber(int n, int a, int b) {
		
        int gcd = __gcd(a,b),lcm = a * b / gcd;
        
        //每个循环节中,a这边会产生 lcm / a - 1 个 不同的数,b这边会产生 lcm / b 的不同的数
        int f1 = lcm / a - 1,f2 = lcm / b;

        //一共会产生cnt个循环节,剩下dis个数
        long long cnt = 1LL * n / (f1 + f2),dis = 1LL * n % (f1 + f2);
        
        long long ans = cnt * lcm % mo;
        long long l = 1,r = 1,pos = 1,now = 0;
		
        //对于剩下的dis个数,循环判断到达第几个数结束
        while(pos <= dis){
            if(l * a < r * b)l ++,now = 0;
            else r ++,now = 1;
            pos ++;
        }
        if(now == 0){
            l --;
            ans = (ans + l * a % mo) % mo;
        }else{
            r --;
            ans = (ans + r * b % mo) % mo;
        }
        return ans;
    }
};

执行用时: 0 ms

内存消耗: 5.7 MB

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值