📜  亨塞尔的引理

📅  最后修改于: 2021-04-24 12:13:26             🧑  作者: Mango

Hensel的引理是为多项式的根规定条件的结果,这些多项式的根将素数的模幂幂“提升”到模的幂次幂根。证明中概述的提升方法使人联想到牛顿法求解方程。说要解决以下类型的方程式:

(x^3 - a) mod \; p^k = 0

这个想法是使用Hensel的引理来解决这种一致性。它也被称为Hensel的“提升”引理,这是模块化算术的结果。如果f是多项式函数并且p是素数,则如果f(a 1 )= 0(mod p)[f’(a 1 )] mod p!= 0 ,则可以“提升”该解决方案通过使用以下递归,得出f(x)= 0(mod p k )的解。注意[f’(a 1 )] -1是指f’(a 1 )模p的模逆。

范例1:

首先,求解(x = 2是mod 5的解)

范例2:

这没有解决方案,因为(x 3 – 3)%mod 7 = 0没有解决方案

以下是Hensel的引理的实现:

C++
// C++ program to illustrate the
// Hensel's Lemma
#include 
using namespace std;
 
// Consider f(x) = x ^ 3 - k,
// where k is a constant
 
// Function to find the modular
// inverse of a modulo m
int inv(int a, int m)
{
    int m0 = m, t, q;
    int x0 = 0, x1 = 1;
    if (m == 1)
        return 0;
 
    // Apply the Euclidean algorithm,
    // to find the modular inverse
    while (a > 1) {
        q = a / m;
        t = m;
        m = a % m;
        a = t;
        t = x0;
        x0 = x1 - q * x0;
        x1 = t;
    }
    if (x1 < 0)
        x1 += m0;
    return x1;
}
 
// Function to find the derivative of
// f(x) and f'(x) = 3 * (x ^ 2)
int derivative(int x)
{
    return 3 * x * x;
}
 
// Function to find the image of
// x in f(x) = x ^ 3 - k.
int Image(int x, int k)
{
    return x * x * x - k;
}
 
// Function to find the next power
// of the number
int next_power(int a_t, int t, int a1,
               int prime, int k)
{
    // Next power of prime for which
    // solution is to be found
    int power_p = (int)pow(prime, t + 1);
 
    // Using Hensel's recursion to
    // find the solution (next_a) for
    // next power of prime
    int next_a = (a_t
                  - Image(a_t, k)
                        * inv(derivative(a1),
                              prime))
                 % power_p;
 
    // If next_a < 0 return equivalent
    // positive remainder modulo p
    if (next_a < 0)
        return next_a += power_p;
 
    // Return the next power of a
    return next_a;
}
 
// Function to find the solution of
// the required exponent of prime
int powerOfPrime(int prime, int power,
                 int k, int a1)
{
    // The lemma does not work for
    // derivative of f(x) at a1
    if (derivative(a1) != 0) {
        int a_t = a1;
 
        // Looping from 1 to power
        // of prime whose solution
        // is to be found
        for (int p = 1; p < power; p++) {
            a_t = next_power(a_t, p,
                             a1, prime, k);
        }
 
        // Final answer after evaluating
        // all the exponents up till
        // the required exponent
        return a_t;
    }
 
    return -1;
}
 
// Driver Code
int main()
{
    int prime = 7, a1 = 3;
    int power = 2, k = 3;
 
    // Function Call
    cout << powerOfPrime(prime, power,
                         k, a1);
 
    return 0;
}


Java
// Java program to illustrate the
// Hensel's Lemma
import java.util.*;
 
class GFG{
 
// Consider f(x) = x ^ 3 - k,
// where k is a constant
 
// Function to find the modular
// inverse of a modulo m
static int inv(int a, int m)
{
    int m0 = m, t, q;
    int x0 = 0, x1 = 1;
     
    if (m == 1)
        return 0;
 
    // Apply the Euclidean algorithm,
    // to find the modular inverse
    while (a > 1)
    {
        q = a / m;
        t = m;
        m = a % m;
        a = t;
        t = x0;
        x0 = x1 - q * x0;
        x1 = t;
    }
    if (x1 < 0)
        x1 += m0;
         
    return x1;
}
 
// Function to find the derivative of
// f(x) and f'(x) = 3 * (x ^ 2)
static int derivative(int x)
{
    return 3 * x * x;
}
 
// Function to find the image of
// x in f(x) = x ^ 3 - k.
static int Image(int x, int k)
{
    return x * x * x - k;
}
 
// Function to find the next power
// of the number
static int next_power(int a_t, int t, int a1,
                      int prime, int k)
{
     
    // Next power of prime for which
    // solution is to be found
    int power_p = (int)Math.pow(prime, t + 1);
 
    // Using Hensel's recursion to
    // find the solution (next_a) for
    // next power of prime
    int next_a = (a_t - Image(a_t, k) *
                  inv(derivative(a1), prime)) %
                  power_p;
 
    // If next_a < 0 return equivalent
    // positive remainder modulo p
    if (next_a < 0)
        return next_a += power_p;
 
    // Return the next power of a
    return next_a;
}
 
// Function to find the solution of
// the required exponent of prime
static int powerOfPrime(int prime, int power,
                        int k, int a1)
{
     
    // The lemma does not work for
    // derivative of f(x) at a1
    if (derivative(a1) != 0)
    {
        int a_t = a1;
 
        // Looping from 1 to power
        // of prime whose solution
        // is to be found
        for(int p = 1; p < power; p++)
        {
            a_t = next_power(a_t, p,
                             a1, prime, k);
        }
 
        // Final answer after evaluating
        // all the exponents up till
        // the required exponent
        return a_t;
    }
    return -1;
}
 
// Driver Code
public static void main(String []args)
{
    int prime = 7, a1 = 3;
    int power = 2, k = 3;
     
    // Function Call
    System.out.print(powerOfPrime(prime, power,
                                  k, a1));
}
}
 
// This code is contributed by rutvik_56


C#
// C# program to illustrate the
// Hensel's Lemma
using System;
class GFG
{
 
// Consider f(x) = x ^ 3 - k,
// where k is a constant
 
// Function to find the modular
// inverse of a modulo m
static int inv(int a, int m)
{
    int m0 = m, t, q;
    int x0 = 0, x1 = 1;  
    if (m == 1)
        return 0;
 
    // Apply the Euclidean algorithm,
    // to find the modular inverse
    while (a > 1)
    {
        q = a / m;
        t = m;
        m = a % m;
        a = t;
        t = x0;
        x0 = x1 - q * x0;
        x1 = t;
    }
    if (x1 < 0)
        x1 += m0;      
    return x1;
}
 
// Function to find the derivative of
// f(x) and f'(x) = 3 * (x ^ 2)
static int derivative(int x)
{
    return 3 * x * x;
}
 
// Function to find the image of
// x in f(x) = x ^ 3 - k.
static int Image(int x, int k)
{
    return x * x * x - k;
}
 
// Function to find the next power
// of the number
static int next_power(int a_t, int t, int a1,
                      int prime, int k)
{
     
    // Next power of prime for which
    // solution is to be found
    int power_p = (int)Math.Pow(prime, t + 1);
 
    // Using Hensel's recursion to
    // find the solution (next_a) for
    // next power of prime
    int next_a = (a_t - Image(a_t, k) *
                  inv(derivative(a1), prime)) %
                  power_p;
 
    // If next_a < 0 return equivalent
    // positive remainder modulo p
    if (next_a < 0)
        return next_a += power_p;
 
    // Return the next power of a
    return next_a;
}
 
// Function to find the solution of
// the required exponent of prime
static int powerOfPrime(int prime, int power,
                        int k, int a1)
{
     
    // The lemma does not work for
    // derivative of f(x) at a1
    if (derivative(a1) != 0)
    {
        int a_t = a1;
 
        // Looping from 1 to power
        // of prime whose solution
        // is to be found
        for(int p = 1; p < power; p++)
        {
            a_t = next_power(a_t, p,
                             a1, prime, k);
        }
 
        // Final answer after evaluating
        // all the exponents up till
        // the required exponent
        return a_t;
    }
    return -1;
}
 
// Driver Code
public static void Main(string []args)
{
    int prime = 7, a1 = 3;
    int power = 2, k = 3;
     
    // Function Call
    Console.Write(powerOfPrime(prime, power,
                                  k, a1));
}
}
 
// This code is contributed by pratham76.


输出:
6

时间复杂度: O(log N)
辅助空间: O(1)