1 条题解

  • 0
    @ 2026-4-13 9:20:59

    题目重述

    给定正整数 a,b,la,b,l,要求找到所有满足

    l=kaxbyl = k \cdot a^x \cdot b^y

    的不同 kk 值的个数,其中 x,y,kx,y,k 都是非负整数。


    核心思想

    由等式 l=kaxbyl = k \cdot a^x \cdot b^y 可得:

    k=laxbyk = \frac{l}{a^x \cdot b^y}

    因此,kk 必须是整数,即 axbya^x \cdot b^y 必须能整除 ll


    关键观察

    1. xxyy 的范围有限

      • 因为 a2a \ge 2,当 xx 增大时,axa^x 增长很快。
      • 220=1,048,5762^{20} = 1,048,576 已经超过 ll 的最大值 10610^6
      • 所以 xx 最多到 2020 左右,yy 同理。
      • 标程中用了 3434 作为上限(234>1062^{34} > 10^6 很多,足够安全)。
    2. 枚举所有可能的 (x,y)(x,y) 组合

      • 先固定 xx,从 ll 中除去 axa^x 得到中间值 x_valx\_val
      • 然后从这个中间值中不断除去 bb 的幂次,得到不同的 kk
      • set 自动去重。

    标程详解

    void solve(int tc){
        int a, b, l;
        cin >> a >> b >> l;
        set<int> ans;
        
        for(int i = 0; i <= 34; ++i){        // i 表示 x 的值
            int x = l;
            bool fail = false;
            
            // 从 l 中除去 a^i
            for(int _ = 0; _ < i; ++_){
                if(x % a){                    // 如果不能整除,说明这个 i 不可行
                    fail = true;
                    break;
                }
                x /= a;
            }
            if(fail) break;                   // 如果 a^i 不能整除 l,更大的 i 也不行
            
            // 现在 x = l / a^i
            // 不断从 x 中除去 b 的幂次,得到不同的 k
            while(true){
                ans.insert(x);                // 当前 x 就是一个可行的 k
                if(x % b) break;              // 如果不能继续除 b,就停止
                x /= b;
            }
        }
        cout << ans.size();
    }
    

    算法流程示例

    以第一个样例 a=2,b=5,l=20a=2,b=5,l=20 为例:

    • i=0i=0x=0x=0):x=20x=20,然后不断除 55

      • 20ans{20}20 \to ans\{20\}20%5=020\%5=0,除以 5544
      • 4ans{20,4}4 \to ans\{20,4\}4%504\%5\neq0,停止
    • i=1i=1x=1x=1):x=20/2=10x=20/2=10,然后除 55

      • 10ans{20,4,10}10 \to ans\{20,4,10\}10%5=010\%5=0,除以 5522
      • 2ans{20,4,10,2}2 \to ans\{20,4,10,2\}2%502\%5\neq0,停止
    • i=2i=2x=2x=2):x=20/4=5x=20/4=5,除 55

      • 5ans{20,4,10,2,5}5 \to ans\{20,4,10,2,5\}5%5=05\%5=0,除以 5511
      • 1ans{20,4,10,2,5,1}1 \to ans\{20,4,10,2,5,1\}1%501\%5\neq0,停止
    • i=3i=3x=20/8x=20/8 不是整数,失败,循环结束

    最终 ans={1,2,4,5,10,20}ans = \{1,2,4,5,10,20\},共 66 个。


    复杂度分析

    • 外层循环 ii 最多 3434
    • 内层每次最多除 bblogbl\log_b l
    • 总复杂度 O(34logbl)O(34 \cdot \log_b l),非常快

    总结

    关键点

    1. 注意到 x,yx,y 的取值范围很小(00 到约 2020
    2. 枚举所有可能的 axa^x,然后从 l/axl/a^x 中不断除去 bb 的幂次
    3. 用集合自动去重

    这种方法简单高效,完全满足题目 t104,l106t \le 10^4, l \le 10^6 的限制。

    • 1

    信息

    ID
    6504
    时间
    1000ms
    内存
    256MiB
    难度
    4
    标签
    递交数
    0
    已通过
    0
    上传者