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