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ới đề trên
ta có thể dùng thuật toán đơn giản: là
cho vòng lặp cho N chạy từ 1 đến A và tính NN chia hết cho A và xuất
N như đề bài với thuận toán trên ta có đoạn mã sau:
#include <iostream>
#include <math.h>
using namespace std;
void main ()
{
int in,ia;//in la N, ia la
A
cout<<"nhap so nguyen A (1<=A<=10^9)"<<endl;
cin>>ia;
for(in=0;in<=ia;in++)//cho
N chay tu 1 den A
{
if((int)pow(float(in),(float)in)%ia==0)// tinh N ngu N tim se chia het cho A khong
break;
if(in==ia)// bang A tinh
dung vong lap
break;
}
cout<<"so nguyen N phu hop voi dieu kien de bai la "<<in<<endl;//xuat ra ket qua
system("pause");
Ta có thể thấy được hạn chế của
thuật toán này phụ thuộc vào quá nhiều khả năng lưu trữ của máy tính. Nên với số
quá lớn thì ta sẽ không tính NN để không sử dụng quá nhiều vào khả nẳng
lưu trữ của máy tính. Vậy phải tìm một thuật toán tìm được N mà không cần tính
NN. Có thể thấy điểm quan trọng của bài toán là phép chia hết. Vậy
ta phải tìm hiểu rõ tính chất chia hết.Theo nguồn tìm kiếm trên mạng, ta có định
lý cơ bản của số học: “Định lý cơ bản của
số học (hay định lý về sự phân tích duy nhất ra các thừa số nguyên tố) phát biểu
như sau: Mọi số tự nhiên lớn hơn 1 có thể viết một cách duy nhất (không kể sự
sai khác về thứ tự các thừa số) thành tích các thừa số nguyên tố”...
“Một cách tổng quát: Mọi số tự nhiên
n lớn hơn 1, có thể viết duy nhất dưới dạng:
trong đó là
các số nguyên tố. Vế phải của đẳng thức này được gọi là dạng phân tích tiêu
chuẩn của n”. nguồn
vậy ta có thể thấy số nguyên
A có thể phân tích thành tích các thừa số nguyên tố. Vậy để NN chia
hết cho A phải thỏa 2 điệu kiện:
-khi phân tích ra phải có
các thừa số nguyên tố giống A.
- phải lớn hơn A tức số mũ của
các thừa số nguyên lớn hơn của A.
Với đề bài cho 1 ≤
A ≤ 109 thì khi phân
tích thừa số nguyên tố với mũ 1 thì ta có 3 trường hợp:
Trường hợp chỉ có 1
số nguyên tố , với các số 2,3,5,7 thì ta phải tìm số mũ để nó thỏa mãn điều kiện
để NN lớn hơn A. Nếu từ
11,13,… thì N sẽ bằng chính nó vì 1111>109.
Trường hợp
2 số nguyên tố trở lên, thì ta thấy chỉ có 2 và 3 phải xét độ lớn NN
còn các trường hợp còn lại thì nó sẽ chính bằng N vì với 2 và 5 tức 1010>109.
Vậy làm sao tính độ lớn NN
khi ta đã chủ động tránh nó.
Đối với chỉ
có 1 thừa số nguyên tố 2, 3, 5, 7 thì ta có: do cơ số của A và N bằng nhau và bằng
thừa số nguyên tố tìm được nên để giảm độ lớn của phép tính thì ta chỉ so sánh
mũ của A và N
Với x.Nx>a
-
x là số mũ cần
tìm
-
N là thừa số
nguyên tố
-
a là số mũ của
nguyên A
vậy công việc của chỉ cần
tìm x.
Đối với trường
hợp thừa số nguyên tố 2 và 3 thì với mũ 1 tức N=6 thì sẽ giới hạn A < 66.
Vậy có cần tính NN không hay tính số mũ như trên. Nếu chú ý thì ta sẽ
thấy giới hạn của A ≤ 109
vậy ta phải tìm số mũ lớn 9 như nhỏ nhất. Nếu phải tính mũ thông thường thì rất
phức tạp làm cho thuật toán dài thêm. Vậy ta phải tìm N sao cho lớn hơn 9 và nhỏ
nhất. vậy từ 2 và 3 số N chỉ có thể là 12. Với 22.3 < 2.33
. vậy đối với A < 66 thì
N=12.
Theo các suy luân trên ta có
thuật toán:
-
Phân tích A thành thừa số nguyên tố có mũ là 1
-
Sẽ các trường hợp đặc biệt: 2, 3 ,5 ,7; 2 và 3
#include <iostream>
#include <math.h>
using namespace std;
void timsonguyento(unsigned int& it,unsigned int in)
//ham kiem tra so nguyen to
{
unsigned int im;
im=2;
it=1;
while(im<in)
{
if(in%im==0)
{
it=0;
break;
}
im++;
}
}
void songuyento (unsigned int in,unsigned int& ib)// ham phan
tich 1 so thanh tich cua cac so nguyen to
{
unsigned int im,it;
im=1;
while(im<=in)
{
if (in%im==0)
timsonguyento(it,im);
if(it==1)
if(in%im==0)
ib*=im;
im++;
}
}
void motsonguyento (unsigned int ia,unsigned int& in)
//ham kiem tra cac truong hop 1 so nguyen to
{
int ib,ic;
for(ib=1;ia>in;ib++)
{
ia=ia/in;
}
for(ic=0;1!=0;ic++)
{
if((ic*pow((float)in,(float)ic))>ib)
{
in=pow((float)in,(float)ic);
break;
}
}
}
void main ()
{
unsigned int ia,in=1;
do
{
cout<<"nhap so nguyen A
(1<=A<=10^9) "<<endl;
cin>>ia;
} while(ia<=0);
songuyento(ia,in);
if(in==2||in==3||in==5||in==7)
motsonguyento(ia,in);
if(in==6)
//ham kiem tra truong hop 2 va 3
{
if(ia<pow(6.0,6))
in=6;
else
in=12;
}
cout<<"N nho nhat de cho N ngu N
chia het cho A la "<<in<<endl;
system("pause");
}
Không có nhận xét nào:
Đăng nhận xét