PVA – Archives

Sưu tầm những bài viết hay trên internet…

Bài toán kiểm tra số nguyên tố

Có lẽ một trong những bài toán mà tất cả các lập trình viên đều gặp phải khi học lập trình cũng như khi tham gia vào các cuộc thi lập trình là bài toán kiểm tra một số nguyên có phải là một số nguyên tố hay không.

Có rất nhiều dạng phát biểu khác nhau của bài toán nhưng suy cho cùng, các lập trình viên vẫn phải viết một hàm kiểm tra với input là 1 số nguyên n, output là đúng (TRUE – 1) nếu n là một số nguyên tố và sai (FALSE – 0) nếu n không phải là một số nguyên tố. Các thuật toán kiểm tra số nguyên tố mà tôi trình bày với các bạn trong bài viết này chỉ là các thuật toán hết sức đơn giản, nhưng đủ sức đáp ứng cho nhu cầu của các lập trình viên trong các cuộc thi lập trình cũng như những công việc đòi hỏi xử lý những số nguyên không quá lớn.
Trước hết cũng nên nhắc lại khái niệm số nguyên tố (prime number): số nguyên tố là số nguyên dương chỉ chia hết cho 1 và chính nó. Theo định nghĩa này số nguyên tố là số tự nhiên và chỉ có hai ước số phân biệt, đó chính là số 1 và bản thân nó. Từ đó suy ra số 1 không phải là một số nguyên tố (có rất nhiều sinh viên mới học lập trình nhầm số 1 là số nguyên tố). Một kết quả khác cũng không kém quan trọng được rút ra đó là số 2 là số nguyên tố đầu tiên (nhỏ nhất) và cũng là số nguyên tố chẵn duy nhất.
Như vậy để kiểm tra một số nguyên có là số nguyên tố hay không, theo suy nghĩ trực quan của tất cả các lập trình viên hay thậm chí một người không hiểu biết gì về thuật toán thì chúng ta cần kiểm tra xem số đó có ước số nào khác 1 và chính nó hay không, nếu có thì đó là hợp số (combine number) còn nếu không có số nào thì đó chính là một số nguyên tố. Thuật toán đầu tiên đến với chúng ta đó là: kiểm tra các số có khả năng là ước số của n (số cần kiểm tra tính nguyên tố), các số này nằm trong khoảng từ 2 tới n – 1. Thuật toán được cài đặt bằng C đơn giản như sau:

int ktnguyento1(int n)
{
 // hàm kiểm tra n có là số nguyên tố hay không
 // kết quả: 1 nếu đúng, 0 nếu sai
 int i;
 int kq = 1; // gia sử n là số nguyên tố
 for(i=2;i
 if(n % i == 0)
 {
  // n có ước số là i, không cần kiểm tra tiếp các giá trị tiếp theo
  kq = 0;
  break;
 }
 return kq;
}

Cài đặt này rất dễ dàng chuyển thành các cài đặt trên các ngôn ngữ khác nhau Pascal, C++ … Tuy nhiên trong ngôn ngữ C khi gặp lệnh return hàm sẽ kết thúc nên cài đặt trên có thể chuyển thành dạng ngắn gọn như sau:

int ktnguyento1(int n)
{
 // hàm kiểm tra n có là số nguyên tố hay không
 // kết quả: 1 nếu đúng, 0 nếu sai
 int i;
 for(i=1;i<=n;i++)
  if(n % i == 0) return 0;
 return 1;
}

Hàm này vẫn chưa đúng hoàn toàn vì khi n = 1 kết quả chạy hàm là: 1 là số nguyên tố vì thế nên cần sửa lại như sau:

int ktnguyento1(int n)
{
// hàm kiểm tra n có là số nguyên tố hay không
// kết quả: 1 nếu đúng, 0 nếu sai
 int i;
 if (n==1)
  return 0;
 for(i=1;i<=n;i++)
  if(n % i == 0) return 0;
 return 1;
}

Một số sinh viên lại cài đặt thuật toán theo kiểu khác như sau:

int ktnguyento0(int n)
{
 // hàm kiểm tra n có là số nguyên tố hay không
 // kết quả: 1 nếu đúng, 0 nếu sai
 int i;
 int dem = 0; // đếm tổng các ước của n
 for(i=1;i<=n;i++)
  if(n % i == 0) dem = dem + i;
 if(dem==n+1) return 1;
 return 0; // tương tự như else return 0;
}

Về cài đặt thì khác nhau nhưng đều là kiểm tra các ước số của n với các ứng cử viên là từ 2 (1) cho tới n-1 (n) và tất nhiên thuật toán kiểu cộng các ước số này sẽ chạy chậm hơn trong đa số các trường hợp. Một số sinh viên lại cài đặt khác đôi chút: thay vì đếm tổng các ước số, ta đếm số các ước số lưu vào biến dem, cuối cùng so sánh biến dem với 2 để kết luận.
Trong các cài đặt trên, nếu n là số nguyên tố thì vòng lặp for sẽ chạy tới khi i = n – 1 để có thể đưa ra kết luận cuối cùng. Tuy nhiên, suy nghĩ thêm một chút chúng ta sẽ thấy rằng không cần phải kiểm tra đến giá trị i = n – 1 mà thực chất chỉ cần tới n/2 (n div 2) vì không có ước số nào của n lớn hơn n/2. Vì vậy thuật toán 2 sẽ là như sau:

int ktnguyento2(int n)
{
// hàm kiểm tra n có là số nguyên tố hay không
// kết quả: 1 nếu đúng, 0 nếu sai
int i;
 if (n==1)
  return 0;
 for(i=2;i<=n/2;i++)
  if(n % i == 0) return 0;
 return 1;
}

Lại suy nghĩ thêm một chút chúng ta sẽ thấy rằng cũng không cần thiết phải kiểm tra đến giá trị n/2 mà chỉ cần đến căn bậc 2 của n là được (các bạn hãy tính toán một chút để thấy tại sao lại như vậy?). Do đó thuật toán mới (3) là như sau:

int ktnguyento3(int n)
{
 int i;
 if (n==1)
  return 0;
 for(i=2;i<=(int)sqrt(n);i++)
  if(n % i == 0) return 0;
 return 1;
}

Ở đây chúng ta cần chú ý đôi chút vì nếu chỉ để như trên thì đôi khi chương trình của chúng ta chạy không đúng, lý do là C có hai hàm sqrt để lấy căn bậc hai của một số; hàm thứ nhất là dành cho các số thực kiểu double (hàm này là hàm mà chúng ta dùng ở trên), hàm thứ hai dành cho các số phức, và bình thường nếu không include file math.h thì Turbo C sẽ dùng hàm dành cho các số phức (file complex.h, DevCpp không bị hiện tượng này).
Với cài đặt trên vẫn có thể có cải tiến được (hầu hết các sinh viên và những người mới học lập trình không để ý điều này), đó là thay vì mỗi lần lặp đều tính sqrt(n) ta chỉ cần tính một lần trước khi thực hiện vòng lặp:

int ktnguyento3(int n)
{
int i;
int m;
if (n==1)
 return 0;
m = (int)sqrt(n);
for(i=2;i<=m;i++)
 if(n % i == 0) return 0;
return 1;
}

Thực tế chạy chương trình cho thấy nếu để nguyên cài đặt thuật toán 2 ở trên thì kết quả chạy lại chậm hơn thuật toán 1 vì mỗi bước đều phải thực hiện phép chia đối với n, nên cần phải chỉnh lại cài đặt của thuật toán 2 giống như thuật toán 3: tính m = n/2 trước khi chạy vòng lặp mới đạt được hiệu quả.
Lại để ý rằng các số nguyên tố chỉ có thể là các số lẻ trừ số 2, và do đó chúng không thể chia hết cho các số chẵn nên ta chỉ cần kiểm tra các ước số (giá trị của i) là số lẻ, do vậy thuật toán tiếp theo (4) sẽ như sau:

int ktnguyento4(int n)
{
int i;
int m;
if(n == 2)
 return 1;
if (n == 1||n % 2 == 0)
 return 0;
m = (int)sqrt(n);
for(i=3;i<=m;i=i+2)
 if(n % i == 0) return 0;
return 1;
}

Rõ ràng so với thuật toán trước đó, số giá trị của i cần kiểm tra giảm đi một nửa. Như vậy mấu chốt trong việc tăng tốc và cải tiến thuật toán nằm ở câu lệnh thay đổi giá trị của biến điều khiển i, ta chỉ cần giảm số giá trị của i cần kiểm tra là sẽ dẫn tới một thuật toán hiệu quả hơn.
Vừa rồi ta đã loại bỏ được một nửa số giá trị của i bằng cách xét ước số 2 có thể có của n. Tiếp theo ta sẽ cải tiến thuật toán bằng cách xét ước số nguyên tố tiếp theo có thể có của n là số 3. Nếu n chia hết cho 2 hoặc 3 thì dễ dàng kết luận nó là hợp số (tất nhiên n phải khác hai giá trị đó). Ngược lại n sẽ có ước số có dạng , , ta sẽ bắt đầu với giá trị i = 5 nên sẽ chọn công thức . Nhưng nếu chỉ kiểm tra i sẽ thiếu mất ứng cử viên ở dạng nên ta sẽ kiểm tra thêm giá trị i+2 ( ) cho đủ. Vậy thuật toán mới (5) sẽ là như sau:

int ktnguyento5(int n)
{
 int i;
 int m;
 if(n == 2 || n == 3)
  return 1;
 if (n == 1||n % 2 == 0||n % 3 == 0)
  return 0; 
 m = (int)sqrt(n);
 for(i=5;i<=m;i=i+6)
  if(n % i == 0 || n % (i+2) == 0) return 0;
 return 1;
}

Cũng có thể cài đặt thuật toán này dựa vào nhận xét sau: nếu ta bắt đầu bằng số i = , thì lần sau sẽ cần cộng i với 2 để kiểm tra giá trị tiếp theo của i (khi đó i sẽ có dạng ), lần sau nữa sẽ cộng i với 4 (để i lại có dạng ), lần tiếp theo lại là 2… Từ nhận xét này dẫn tới cài đặt sau (không hiệu quả hơn cài đặt trên khi chạy trên thực tế):

int ktnguyento51(int n)
{
int i;
int m, y;
if(n == 2 || n == 3)
 return 1;
if (n == 1||n % 2 == 0||n % 3 == 0)
 return 0;
m = (int)sqrt(n);
y = 2;
for(i=5;i<=m;i=i+y, y = 6 - y)
 if(n % i == 0) return 0;
return 1;
}

Trong các bài toán mà việc kiểm tra số nguyên tố bị lặp lại nhiều lần ta cũng có thể cải thiện thuật toán kiểm tra tính nguyên tố của một số nguyên bằng cách chỉ kiểm tra các ước số có thể có của n nhưng là số nguyên tố, vì nếu n là hợp số thì chắc chắn sẽ chia hết cho một số nguyên tố nào đó nhỏ hơn nó. Vì vậy ta sẽ sinh trước một mảng các số nguyên tố (về bản chất là đánh dấu các số đó là số nguyên tố) không vượt quá giới hạn của n (giá trị lớn nhất của n). Sau đó khi kiểm tra các ước số của n chỉ cần kiểm tra xem n có chia hết cho các số nguyên tố nhỏ hơn căn bậc hai của n nằm trong mảng đã cho hay không. Để làm việc này có một thuật toán nổi tiếng gọi là sàng Erastosthene như sau:

const int MAX_N = 10000; // giá trị lớn nhất của n
int nt[MAX_N]; // mảng đánh dấu, nt[i] = 0 nếu i là số nguyên tố, 1 nếu ngược lại

void sangnt(int n)
{
 // đánh dấu các số nguyên tố nhỏ hơn n
 int i, k;
 for (i=2; i<n; i++)
  if (nt[i] == 0) // nếu i là số nguyên tố thì các bội của i sẽ là hợp số
  {
    k = 2;
    // đánh dấu các bội số của i
    while (k*i<n)
      nt[i*k++] = 1;
  }
}

Kết luận.
Qua việc trình bày các thuật toán đơn giản để kiểm tra các số nguyên tố nhỏ, tôi hy vọng mang đến cho các bạn một thuật toán tốt để có thể sử dụng trong các cuộc thi lập trình hay các bài toán trong phạm vi nhỏ, đồng thời qua đó minh họa quá trình tinh chỉnh cài đặt một thuật toán. Có thể cùng một thuật toán nhưng với các cài đặt khác nhau, hiệu quả sẽ khác nhau, và nhiều khi hiệu quả đó lại dựa trên những chi tiết tưởng chừng như rất nhỏ nhặt, không đáng lưu tâm.
Mặc dù đã hết sức thận trọng và xem xét kỹ các ví dụ đưa ra trong bài viết, tuy vậy vẫn có thể không tránh khỏi các sai sót, rất mong nhận được sự đóng góp ý kiến của các bạn độc giả. Mọi góp ý, thắc mắc xin gửi về địa chỉ email: tuannhtn@yahoo.com.
Nguyễn Hữu Tuân

About these ads

30 responses to “Bài toán kiểm tra số nguyên tố

  1. duc liketec 12/01/2010 at 10:13 AM

    hay wa…!

  2. sao cũng đc 20/01/2010 at 10:03 PM

    bài này giải dễ mà sao mà dài vậy.
    var n:lọngint;
    kt:boolean;
    begin
    readln(x);
    kt:true;
    for i:=1 to n do
    begin
    for i:=2 to n do
    if n mod i = 0 then kt:= false
    else kt:=true;
    end.
    end.
    bài này làm kiểu này nhanh hơn nhiều. Vì số nguyên tố chỉ cần nhiều hơn 2 ước thôi. bài này chưa hoàn chỉnh tui chỉ giới thiệu thêm thôi

  3. vuau 21/01/2010 at 7:02 PM

    Truong hop so khong phai la nguyen to, chuong trinh cua ban phai duyet tu 1 den n, chay cham khi n la so lon.

  4. uranus13 22/01/2010 at 12:50 AM

    Cái mã cuối dựa trên sàng Eres thì phải.:”> Sorry, mình ko nhớ rõ tên lắm.

  5. uranus13 22/01/2010 at 12:53 AM

    à ko phải, sorry lần nữa, cái kia chỉ dùng được với số nhỏ hơn 100 thôi

  6. anhthebk 19/03/2010 at 12:03 PM

    hay day.tui cung dang can may thu nay.no se giup tui rat nhiu dayZz

  7. zXcongducXz 22/03/2010 at 6:03 AM

    Mấy cái vòng lặp for bị mất tiêu rồi sao coi chời

  8. quan 19/04/2010 at 10:02 PM

    hay wa ..! thx so much

  9. Thế Vinh(Đại học KTCN) 18/08/2010 at 11:07 AM

    pac chủ topic làm như vậy thì hay thật, nhưng sẽ bỏ xót các số 5, 7, 11, 13, 17 kể từ thuật toán thứ 4. Pac phải thêm vài lệnh if ở trên for nữa để bẫy các trường hợp khi cho i=3, thì ngay khi nhập vào n=5 thì vòng for đã lỗi vì sqrt(5) < 3 làm sao for chạy ngay vòng đầu tiên, rồi ngay khi sqrt(7) cũng vậy là 2 trường hợp đã bị bỏ xót. Rồi tới thuật toán thứ 5 khi cho i=5, thì dĩ nhiên bỏ xót 2 trường hợp trên, và tiếp tục bỏ xót các trường hợp n=11, 13, 17,19,23 vì khi cho i= 5 thì sprt(23) nói chung là chỉ sửa lại câu lệnh cho hoàn chỉnh
    Pac làm vậy là quá tốt rồi, tôi chỉ tối ưu thêm dựa vào pac, chứ tôi cũng chưa nghĩ tới mức này.
    Thuật toán như sau:
    int ktnguyento4(int n)
    {
    int i, m;
    if(n == 2 || n == 3 || n==5 || n==7|)
    return 1;
    if (n == 1|| n % 2 == 0 || n % 3 == 0 || n%5==0)
    return 0;
    if (n == 1|| n % 2 == 0)
    return 0;
    m = (int)sqrt(n);
    for(i=3;i nói chung bài này muốn tối ưu tốt hơn thì phải cần nhiều người hợp tác, 1 mình mình ko thể làm nổi
    Nhưng tôi thấy bạn chủ topic làm rất tốt, vào chỉ dựa vào những ý của bạn từ thuật toán đầu tới cuối để lập luận phân tích thêm.
    Và tôi mong các bạn nên đóng góp thêm dùm, vì chắc chắn tôi tối ưu sẽ còn xót. Và để topic của bạn này càng ngày tốt hơn.

    • gagoit 22/11/2011 at 6:56 PM

      for(i=5;i<=m;i=i+6)
      if(n % i == 0 || n % (i+2) == 0) return 0;
      return 1;

      Thuật toán trên của chủ topic ko thiếu đâu bạn à. n=5 or 7 (cac số có sqrt<5) thì ko có for do vậy nó return 1 (trừ các số % 2 or 3 ==0) .

  10. Thế Vinh(Đại học KTCN TP HCM) 18/08/2010 at 11:13 AM

    chết ko, post ko biết sao cái phần thuật toán nó bị chèn mất khúc cuối, tôi xin post lại chổ đó
    int ktnguyento4(int n)
    {
    int i, m;
    if(n == 2 || n == 3 || n==5 || n==7|)
    return 1;
    if (n == 1|| n % 2 == 0 || n % 3 == 0 || n%5==0)
    return 0;
    if (n == 1|| n % 2 == 0)
    return 0;
    m = (int)sqrt(n);
    for(i=3;i<=m;i=i+2)
    if(n % i == 0)
    return 0;
    return 1;
    }

    • Nguyễn Đoàn Thanh Hải 02/10/2012 at 10:17 PM

      thuật toán của bạn khá đc đó, ý tưởng đc nhưng viết hỏng rồi… bạn sử dụng if trùng trường hợp nên khi chạy ct nó sẽ ra kết quả sai cho mà xem

  11. hamhochoi 20/08/2010 at 4:46 PM

    mong các bác chỉ thêm nhiều
    int ktnguyento(int n){
    if (n==2||n==3||n==5||n==7||n==11)
    return 1;
    else if (n%2!=0 && n%3!=0 && n%5!=0 && n%7!=0 && n%11!=0)
    return 1;
    else
    return 0;
    }

  12. C++ 11/09/2010 at 3:07 AM

    #include
    #include
    void main (){
    int n;
    cout<>n;
    int i;
    if (n==1)
    cout<<n<<" khong phai la snt";
    for(i=2;i<=(int)sqrt(n);i++)
    if(n % i == 0)
    cout<<n<<" khong phai la snt";
    else cout<<n<<" la snt" ;
    }

    Bác xem giúp em! em chạy với số chính phương lại nó có vấn đề vậy?
    thanks!

  13. cvav 28/10/2010 at 9:16 AM

    Mình cũng thường dùng cái này trong khi làm bài tập C/C++
    Nó là hàm khôg thể thiếu trong nhiều bài toán (như phân tích 1 số ra thừa số nguyên tố chẳng hạn)
    Mình chạy trên các số nguyên lớn mức hàng triệu vẫn chưa thấy sai.
    Bác nào quan tâm thì test thử nhé
    //////////////////////////////////////////////////////////////////////////////////////////

    bool IsPrimeNumber(const int &x) {
    if(x > 1) { // Chỉ xét số > 1
    if(x = 2; i–) {
    if(x % i == 0)
    return false;
    }
    return true;
    }
    }
    return false;
    }

    ////////////////////////////////////////////////////////////////////////////////////

    • cvav 28/10/2010 at 9:21 AM

      Không hiểu sao post bị lỗi, post lại vậy

      /////////////////////////////////////////////////////////

      bool IsPrimeNumber(const int &x) {
      if(x > 1) { //Chi xet so > 1
      if(x = 2; i–) {
      if(x % i == 0)
      return false;
      }
      return true;
      }
      }
      return false;
      }

      ////////////////////////////////////////////////////////

  14. cvav 28/10/2010 at 9:22 AM

    vẫn bị lỗi. Hết cách rồi. mà sao cái trang này không cho chỉnh sửa bài nhỉ

  15. vuau 07/11/2010 at 10:26 AM

    Ban co the dung cap the

    
    

    de wrap doan. ma~ cua ban
    VD:

    bool IsPrimeNumber(const int &x) {
        if(x > 1) { //Chi xet so > 1
          if(x = 2; i–) {
            if(x % i == 0)
              return false;
          }
          return true;
        }
      }
      return false;
    }
    
  16. Lyon 29/03/2011 at 8:47 PM

    Pascal thì vầy được không ?

    function ktnt(i:longint):boolean;
    var j:longint;
    begin
    If i<2 then exit(false);
    if i mod 2 or 5 or 7 = 0 then exit(true);
    If i mod 2 or 5 or 7 0 then
    For j:=8 to trunc(sqrt(n)) do
    if i mod j = 0 then exit(false);
    Exit(true);
    end;

  17. tran quoc tiep 05/04/2011 at 3:35 PM

    bài này mình làm thế này.
    int ktnguyento(int n)
    {
    if(n<2) return 0;
    for(int i=0;i<(int) sqrt(n);i++)
    if(n%i==0)
    return 0;
    return 1;
    }
    hoàn toàn chính xác.

  18. Huỳnh tấn Vũ 07/04/2011 at 12:10 PM

    các anh các chị có thể viết giúp em chương trình con rồi kiểm tra xem nó có là số nguyên tố không nha nếu đúng thì xuất đúng sai thì ngược lại

  19. Will 26/05/2011 at 10:59 AM

    int ktnguyento1(int n)
    {
    // hàm kiểm tra n có là số nguyên tố hay không
    // kết quả: 1 nếu đúng, 0 nếu sai
    int i;
    int kq = 1; // gia sử n là số nguyên tố
    for(i=2;i
    if(n % i == 0)
    {
    // n có ước số là i, không cần kiểm tra tiếp các giá trị tiếp theo
    kq = 0;
    break;
    }
    return kq;
    }

    dear ban !
    doan code nay:
    vd: N =6 % I=2; THI SE LA = 3, !=0; KQ !=0, NHU VAY , LIEU CO LA SNT KO ???

  20. Thế Anh 30/06/2011 at 12:36 AM

    Mọi người có thể tham khảo thêm trong quyển: Art of Programming Contest – 2nd Edition (trang 102)

  21. Mai Anh 21/09/2011 at 10:42 AM

    thế nếu số nguyên tố đó rất rất lớn thì kiểm tra tn ạ.các anh giúp em với

  22. Uyên Thi 21/09/2011 at 1:23 PM

    giải giúp em Bt này gấp các anh chị ơi:
    nhập hai số nguyên dương m,n. Tính xem từ m đến n có bao nhiêu số nguyên tố

  23. lakchicken 28/10/2011 at 4:24 PM

    //code c
    int ktnguyento(int n)
    {
    if(n==1) return 0;
    for(int i=2;i<n;i++)
    if(n%i==0)
    return 0;

    return 1;
    }

    code này đúng ko nhỉ :D

    @uyenthi : thêm hàm demnguyento() nữa là xong b, chạy từ m đến n rồi dùng hàm ktnguyento() nếu đúng thì tăng biến đem lên :D

  24. Nhai con 11/02/2012 at 3:48 PM

    Cái topic này cũng hơi bị cũ rùi nhỉ, nhưng cho mình ké một chút giải thuật bên C# nha (mình thấy C, C++ hay C# thì cũng tương tự nhau thôi). Cái giải thuật này do mình nghĩ ra, nếu có thấy kỳ kỳ thì các bạn cũng thông cảm nghen:
    int i, n, x, tam=1;
    Console.Write(“Nhap 1 so nguyen: “);
    n = Convert.ToInt32(Console.ReadLine());
    for (i = 2; i < n; i++)
    {
    x = n % i;
    tam = tam * x;
    }
    if (tam != 0)
    Console.WriteLine("So " + n + " la so nguyen to");
    else Console.WriteLine("So " + n + " khong phai la so nguyen to");

  25. dat 20/09/2012 at 12:31 AM

    #include
    #include
    #include
    int k,i,j,n;
    int max;

    main()
    {

    cout<>max;
    if (max<2)
    cout<<"k co' snt nao";
    else
    j=0;
    for (n=2; n<=max; n++)
    {
    k=floor(sqrt(n));
    i=2;
    while ((n%i!=0)&&(ik)
    {
    if (k%10==0)
    cout<<'\n';
    j=j+1;
    cout<<n<<" ";
    }
    }
    getch();
    return 0;
    }

  26. Cong dong IT Quang Nam 06/01/2013 at 4:55 PM

    I like the helpful information you provide to your articles. I’ll bookmark your weblog and test once more here regularly. I am rather certain I’ll be informed many new stuff proper here! Best of luck for the following!

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.

%d bloggers like this: