先來一個什麼是快速冪運算的講解部落格網址點擊開啟連結,別人寫的
然後理解了什麼是快速冪運算後這裡要寫的就是它的一個應用,包含了埃氏篩法算區間素數的方法
關於埃氏篩法可以看我的另一篇部落格http://blog.csdn.net/qq_34115899/article/details/79498829
題目:Carmichael Numbers (UVa No.10006)
大致意思是:我們把對任意的1<x<n都有xn≡x(mod n)成立的合數n稱為Carmichael Numbers。對於給定的整數n,請判斷它是不是Carmichael Numbers。(批註:a和b除以m後所得的餘數相等記作a≡b(mod m))
限制條件 2<n<65000
範例:
輸入: 輸入: 輸入: 輸入: 輸入: 輸入:
17 561 4 1729 1109 431
輸出: 輸出: 輸出: 輸出: 輸出: 輸出:
NO YES NO YES NO NO
import java.util.Scanner;/*不利用語言特性任何語言都可以寫*/public class Main { public static boolean[] is_prime = new boolean[65001]; public static void main(String[] args) { Scanner cin = new Scanner(System.in); long n = cin.nextLong(); cin.close(); boolean flag = true; sieve(n); // 記錄n以內,哪些是素數 if (is_prime[(int) n]) { // 是素數就不合題意 flag = false; } else { for (int i = 2; i < n; ++i) { // 1<x<n都有xn≡x(mod n)成立,即從1~n的x都有xn mod n恒等於x mod n,滿足就是YES否則NO if (mod_pow(i, n, n) != i % n) { flag = false; break; } } } if (flag) { System.out.println("YES"); } else { System.out.println("NO"); } }/*埃氏篩法原理:先將2到n範圍內的所有整數寫下來。其中最小的數字2是素數。將表中所有2的倍數都划去。表中剩餘的最小數字是3,它不能被更小的數整除,所以是素數。再將表中所有3的倍數都划去。依次類推,如果表中剩餘的最小數字是m時,m就是素數。然後將表中的所有m的倍數都划去。像這樣反覆操作,就能依次枚舉n以內的素數*/ public static void sieve(long n) { // 埃氏篩法複雜度O(nlognlogn)看作線性也可以 is_prime[0] = is_prime[1] = false; for (int i = 2; i <= n; ++i) { is_prime[i] = true; } for (int i = 2; i <= n; ++i) { if (is_prime[i]) { for (int j = i << 1; j <= n; j += i) { is_prime[j] = false; } } } } public static long mod_pow(long x, long n, long mod) { // java的long是64位,c++的long long是64位,long是32位 long res = 1; while (n > 0) { if ((n & 1) == 1) { res = res * x % mod; } x = x * x % mod; n >>= 1; } return res; }}
接下來如果使用java語言特性用BigInteger的話很方便,但可能逾時
import java.math.BigInteger;import java.util.Scanner;public class Main { public static boolean[] is_prime = new boolean[65001]; public static void main(String[] args) { Scanner cin = new Scanner(System.in); int n = cin.nextInt(); cin.close(); boolean flag = true; sieve(n); if (is_prime[n]) { flag = false; } else { for (int i = 2; i < n; ++i) { BigInteger ii = new BigInteger(i + ""); if (ii.pow(n).mod(new BigInteger(n + "")).intValue() != i % n) { flag = false; break; } } } if (flag) { System.out.println("YES"); } else { System.out.println("NO"); } } public static void sieve(long n) { is_prime[0] = is_prime[1] = false; for (int i = 2; i <= n; ++i) { is_prime[i] = true; } for (int i = 2; i <= n; ++i) { if (is_prime[i]) { for (int j = i << 1; j <= n; j += i) { is_prime[j] = false; } } } }}
=============================我是一個反應遲鈍的程式員==========================