Bài 1:
Cho số tự nhiên A. Hãy tìm số tự
nhiên N nhỏ nhất sao cho N lũy thừa
N (nhân N cho chính nó N lần) chia hết cho
A. Hãy viết
chương trình tìm số N đó và xuất ra màn hình. Trong đó A có giá trị: 1 ≤ A ≤ 109
Ví
dụ:
Số nhập vào là A
|
Số xuất ra là N
|
8
|
4
|
13
|
13
|
Giải:
Đặt vấn đề:
- Thông thường khi đọc xong đề bài này ta thường nghĩ ngay đến việc kiểm tra các số tự nhiên N với 1 ≤ N ≤ A để xem NN có chia hết cho A hay không thì xuất ra giá trị cần tìm là N.
- Thông thường khi đọc xong đề bài này ta thường nghĩ ngay đến việc kiểm tra các số tự nhiên N với 1 ≤ N ≤ A để xem NN có chia hết cho A hay không thì xuất ra giá trị cần tìm là N.
Vấn đề:
- Trong ngôn ngữ lập trình C/C++ ta có kiểu số nguyên dài nhất là 32 bit với số nguyên lớn nhất có thể lưu trữ là 232 - 1 = 4294967295.
- Ta lại có 1 ≤ A ≤ 109, giả sử N = 109 thì khi tính NN đã vượt quá giới hạn lưu trữ của máy.
- Ta nghĩ sang hướng giải quyết khác là dung kiểu số thực nhưng như thế ta lại không thể dung phép chia lấy phần dư (%) để chạy chương trình kiểm tra chia hết hay không.
Cách giải quyết bài
toán:
- Theo định lí cơ bản của số học: Mọi số nguyên n > 1 đều biểu diễn được dưới dạng tích của các số nguyên tố. Phân tích này là duy nhất nếu không tính thứ tự của các thừa số.
Như vậy mọi số nguyên n > 1 đều có thể biểu diễn dưới dạng $n = \prod\limits_{i = 1}^k {p_i^{{\alpha _i}}} = p_1^{{\alpha _1}}p_2^{{\alpha _2}}...p_k^{{\alpha _k}},{\alpha _i} > 0$ trong đó pi (i =1,2,…k) là những số nguyên tố đôi một khác nhau. Ta nói n có dạng phân tích chính tắc.
- Theo định lí cơ bản của số học: Mọi số nguyên n > 1 đều biểu diễn được dưới dạng tích của các số nguyên tố. Phân tích này là duy nhất nếu không tính thứ tự của các thừa số.
Như vậy mọi số nguyên n > 1 đều có thể biểu diễn dưới dạng $n = \prod\limits_{i = 1}^k {p_i^{{\alpha _i}}} = p_1^{{\alpha _1}}p_2^{{\alpha _2}}...p_k^{{\alpha _k}},{\alpha _i} > 0$ trong đó pi (i =1,2,…k) là những số nguyên tố đôi một khác nhau. Ta nói n có dạng phân tích chính tắc.
- Ta
có hệ quả sau:
Nếu $n = \prod\limits_{i = 1}^k {p_i^{{\alpha _i}}} $, $m = \prod\limits_{i = 1}^k {p_i^{{\beta _i}}} $, ${\alpha _i},{\beta _i} \geqslant 0$ thì $m \vdots n$ $ \Leftrightarrow {\beta _i} \geqslant {\alpha _i}{\text{ }}(i = 1,2,...,k)$ (1)
- Do đó để giải quyết
bài toán này ta sẽ phân tích A thành tích các thừa số nguyên tố của A (Trong đó
trường hợp A = 1 ta sẽ xét riêng). Từ (1) ta có:
Với $A = p_1^{{\alpha _1}}p_2^{{\alpha _2}}p_3^{{\alpha _3}}....p_k^{{\alpha _k}}$ thì N phải có dạng $N = {p_1}{p_2}{p_3}...{p_k}$ $ \Rightarrow {N^N} = {({p_1}{p_2}{p_3}...{p_k})^N}$ đồng thời $N \geqslant Max\left[ {{a_i}} \right]$ $ \Rightarrow N = k.Tich$ với $Tich = {p_1}{p_2}{p_3}...{p_k}$.
Thuật toán:
- Phân tích A thành tích của các thừa số.
Source code:
- Phân tích A thành tích của các thừa số.
- Đặt Tích bằng tích của các thừa số nguyên tố của A (với số mũ của mỗi số nguyên tố là 1)
- Gán Max[ai] là số mũ cao nhất trong các số mũ của các thừa số nguyên tố của A.
Source code:
#include <stdio.h>
#include <conio.h>
void main()
{
unsigned long A, N, Tich, max, count, k;
Tich = 1;
k = 1;
printf("Nhap
vao so tu nhien A: ");
scanf("%ld", &A);
if (A == 1)
N = 1;
else
{
max = 1;
for (int i=2; i*i<=A; i++)
{
if (A % i == 0)
{
Tich = Tich*i;
count = 0;
while (A % i == 0)
{
count++;
A = A/i;
}
if (count > max)
max = count;
}
}
if (A > 1)
Tich = Tich*A;
while (k*Tich < max)
k++;
N = k*Tich;
}
printf("So
tu nhien N can tim la: %ld\n", N);
getch();
}
Không có nhận xét nào:
Đăng nhận xét