1. 程式人生 > >UVa 11440 - Help Tomisu(歐拉函數 + 問題轉換)

UVa 11440 - Help Tomisu(歐拉函數 + 問題轉換)

ext put targe n-1 index.php font https buffere tst

鏈接:

https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=2435

題意:

給定正整數N和M,統計2和N!之間有多少個整數x滿足:x的所有素因子都大於M(2≤N≤1e7,1≤M≤N,N-M≤1e5)。
輸出答案除以100000007的余數。例如,N=100,M=10時答案為43274465。

分析:

因為M≤N,所以N!是M!的整數倍。“所有素因子都大於M”等價於和M!互素。
另外,根據最大公約數的性質,對於k>M!,k與M!互素當且僅當k mod M!與M!互素。


這樣,只需要求出“不超過M!且與M!互素的正整數個數”,再乘以N!/M!即可。
這樣,問題的關鍵就是求出phi(M!)。因為有多組數據,考慮用遞推的方法求出所有的phifac(n)=phi(n!)。
由phi函數的公式:phi(n) = n(1-1/p1)(1-1/p2)...(1-1/pk),
如果n不是素數,那麽n!和(n-1)!的素因子集合完全相同,因此phifac(n)=phifac(n-1)*n;
如果n是素數,那麽還會多一項(1-1/n),即(n-1)/n,約分得phifac(n)=phifac(n-1)*(n-1)。

代碼:

 1 import java.io.*;
 2 import java.util.*;
3 import static java.lang.Math.*; 4 import static java.util.Arrays.*; 5 6 public class Main { 7 Scanner cin = new Scanner(new BufferedInputStream(System.in)); 8 final long MOD = (long)1e8 + 7; 9 final int UP = (int)1e7 + 5; 10 boolean isp[] = new boolean[UP]; 11 long phifac[] = new
long[UP]; 12 13 void constant() { 14 fill(isp, true); 15 int u = (int)sqrt(UP+0.5); 16 for(int i = 2; i <= u; i++) if(isp[i]) { 17 for(int j = i*i; j < UP; j += i) isp[j] = false; 18 } 19 phifac[1] = phifac[2] = 1; 20 for(int i = 3; i < UP; i++) 21 phifac[i] = phifac[i-1] * (isp[i] ? i-1 : i) % MOD; 22 } 23 24 void MAIN() { 25 constant(); 26 while(true) { 27 int n = cin.nextInt(); 28 int m = cin.nextInt(); 29 if(n + m == 0) break; 30 long ans = phifac[m]; 31 for(int i = m+1; i <= n; i++) ans = ans * i % MOD; 32 System.out.println((ans-1+MOD)%MOD); // 註意這裏要減1,因為題目從2開始統計 33 } 34 } 35 36 public static void main(String args[]) { new Main().MAIN(); } 37 }

UVa 11440 - Help Tomisu(歐拉函數 + 問題轉換)