Mod Tree(扩展BSGS)

本文探讨了一种算法问题——给定一棵每个节点有K个孩子的树,寻找最小的层数D,使得该层的节点数量模P等于N。文章通过扩展BSGS算法解决了这一问题,并提供了完整的AC代码。

Mod Tree

这里写图片描述

 The picture indicates a tree, every node has 2 children.
  The depth of the nodes whose color is blue is 3; the depth of the node whose color is pink is 0.
  Now out problem is so easy, give you a tree that every nodes have K children, you are expected to calculate the minimize depth D so that the number of nodes whose depth is D equals to N after mod P. 

Input
The input consists of several test cases.
Every cases have only three integers indicating K, P, N. (1<=K, P, N<=10^9)
Output
The minimize D.
If you can’t find such D, just output “Orz,I can’t find D!”
Sample Input

3 78992 453
4 1314520 65536
5 1234 67

Sample Output

Orz,I can’t find D!
8
20
题意:

给定每个节点的孩子数K求最小层数使得该层的节点数模P等于N

分析:

即求

KxN (mod P) K x ≡ N   ( m o d   P )

因为P不一定是素数故需要用扩展BSGS

很奇怪的是做了好几道BSGS的题目了,抄模板一直wa,在抄一遍又过了,都不知道哪里错的

ACcode:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
ll q_pow(ll a, ll b, ll mod){
    ll ans = 1;
    while(b){
        if(b & 1) ans = ans * a % mod;
        b >>= 1;
        a = a * a % mod;
    }
    return ans;
}

ll gcd(ll a,ll b){
    return b ? gcd(b,a%b) : a;
}

void ex_gcd(ll a,ll b,ll &x,ll &y){
    if(!b){
        x = 1;
        y = 0;
        return;
    }
    ex_gcd(b,a%b,y,x);
    y -= a / b * x;
    return;
}

ll BSGS(ll a,ll b,ll p){
    a %= p;
    b %= p;
    ll ret = 1;
    for(ll i = 0; i <= 50; i++){
        if(ret == b) return i;
        ret = ret * a % p;
    }
    ll x,y,d,v = 1,cnt = 0;
    while((d = gcd(a,p)) != 1){
        if(b % d) return -1;
        b /= d;
        p /= d;
        v = v * (a / d) % p;
        cnt++;
    }
    map<ll,ll>h;
    ll m = ceil(sqrt(p)),t = 1;
    for(ll i = 0; i < m; i++){
        if(h.count(t)) h[t] = min(h[t],i);
        else h[t] = i;
        t = t * a % p;
    }
    for(ll i = 0; i < m; i++){
        ex_gcd(v,p,x,y);
        x = (x * b % p + p) % p;
        if(h.count(x)) return i * m + h[x] + cnt;
        v = v * t % p;
    }
    return -1;
}

int main(){
    ll k,p,n;
    while(~scanf("%lld%lld%lld",&k,&p,&n)){
        if(n >= p){
            puts("Orz,I can’t find D!");
            continue;
        }
        ll ans = BSGS(k,n,p);
        if(ans == -1) puts("Orz,I can’t find D!");
        else printf("%lld\n",ans);
    }
    return 0;
}
<think> 我们被要求介绍BSGS算法(大步小步算法),根据用户提供的引用内容,用户已经对BSGS有了一定了解(如分块思想、扩展BSGS等),但希望获得更系统的介绍。 我们将按照以下结构组织回答: 1. 问题背景:离散对数问题 2. BSGS算法概述与适用条件(要求模数与底数互质) 3. 算法步骤(分块、建立哈希表、查找匹配) 4. 复杂度分析 5. 扩展BSGS(处理模数与底数不互质的情况) 6. 示例问题(可选,根据篇幅决定) 7. 相关扩展问题 注意:用户提供的引用中已经包含了BSGS的核心思想和扩展BSGS的推导,我们将整合这些信息,并严格按照格式要求(数学公式用$...$和$$...$$)进行表述。 </think> ### BSGS算法详解 BSGS(Baby-Step Giant-Step)算法是求解**离散对数问题**的高效算法,核心思想是通过**分块策略**将暴力枚举的复杂度$O(n)$降为$O(\sqrt{n})$。适用于解决形如: $$A^x \equiv B \pmod{P} \quad (\gcd(A,P)=1)$$ 的最小整数解$x$问题。 --- #### **算法原理与步骤** 1. **问题转化** 设$m = \lceil \sqrt{P} \rceil$,将解表示为: $$x = i \cdot m - j \quad (0 \leq j < m, 1 \leq i \leq m)$$ 则原方程转化为: $$A^{i \cdot m} \equiv B \cdot A^j \pmod{P}$$ 2. **Baby-Step(预处理)** 计算所有$j \in [0, m-1]$的$B \cdot A^j \mod P$并存入哈希表: ```python baby_steps = { (B * pow(A, j, P)) % P : j for j in range(m) } ``` 3. **Giant-Step(搜索匹配)** 计算$C = A^m \mod P$,枚举$i \in [1, m]$: $$T = C^i \mod P$$ 在哈希表中查找$T$,若存在$j$满足$T \equiv B \cdot A^j \pmod{P}$,则解$x = i \cdot m - j$。 4. **终止条件** - 找到匹配:返回$x = i \cdot m - j$ - 无匹配:方程无解 --- #### **复杂度分析** | 步骤 | 时间复杂度 | 空间复杂度 | |----------------|------------|------------| | Baby-Step | $O(\sqrt{P})$ | $O(\sqrt{P})$ | | Giant-Step | $O(\sqrt{P})$ | - | | **总计** | $O(\sqrt{P})$ | $O(\sqrt{P})$ | > 相比暴力枚举$O(P)$,效率提升显著($P=10^{18}$时,$\sqrt{P}=10^9$)。 --- #### **扩展BSGS(处理$\gcd(A,P)\neq1$)** 当$A$与$P$不互质时,需先消除公因子[^2]: 1. **提取公因子** 设$g=\gcd(A,P)$,若$g \nmid B$且$B \neq1$则无解。 方程两边同除$g$: $$A^{x-1} \cdot \frac{A}{g} \equiv \frac{B}{g} \pmod{\frac{P}{g}}$$ 2. **递归转化** 令$A' = A/g, P' = P/g, B' = B/g$,得到新方程: $$A^{x-1} \cdot A' \equiv B' \pmod{P'}$$ 递归至$\gcd(A', P')=1$后用标准BSGS求解。 --- #### **示例** 求解$5^x \equiv 17 \pmod{23}$的最小$x$: 1. 取$m = \lceil\sqrt{23}\rceil = 5$,计算$C=5^5 \mod 23 = 20$ 2. Baby-Step:计算$j \in [0,4]$的$17 \cdot 5^j \mod 23$ → `{17:0, 16:1, 11:2, 9:3, 22:4}` 3. Giant-Step: - $i=1$: $T=20^1 \mod 23=20$(不在表) - $i=2$: $T=20^2 \mod 23=9$ → 查表得$j=3$ 4. 解$x=2 \cdot 5 - 3 = 7$(验证:$5^7 \mod 23=17$ ✓) --- ### **应用场景** 1. 密码学中的离散对数难题(如Diffie-Hellman密钥交换) 2. 椭圆曲线密码体制的安全性分析 3. 区块链技术的私钥恢复场景(需合法授权)[^1] ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值