1. 程式人生 > >【 51NOD 1434 素數篩 】【數論+思維+篩素數】區間LCM【找到一個最小整數M,滿足M>N,LCM(N+1,N+2,..,M-1,M)是LCM(1,2,3,4,.,N-1,N) 的倍數】

【 51NOD 1434 素數篩 】【數論+思維+篩素數】區間LCM【找到一個最小整數M,滿足M>N,LCM(N+1,N+2,..,M-1,M)是LCM(1,2,3,4,.,N-1,N) 的倍數】

思路:

雖然是四級題,但是思路還是不太清晰,找網上題解講的很多不是特別清晰(可以隨便舉些例子理解一下)

首先可以得出一個性質:LCM(1,2,3,4,...,N-1,N) 中質因子k的出現的次數為t,則有k^t<=n

根據這個性質我們先篩出素數,然後列舉每個質數,求出對應的k和t,然後找出倍數j(不會很大),使得j*k^t>n,這個j*k^t是ans的可能取值,所以ans = max(ans, j*k^t)不斷更新最大的ans,這樣可以保證儘量小的m使得LCM(N+1,N+2,....,M-1,M)中存在j*k^t把LCM(1,2,3,4,...,N-1,N)k^t除盡

程式碼:

(個人覺得這個程式碼結合上面的題解容易理解些)

#include <bits/stdc++.h>
using  namespace  std;

template<class T> T sqr(T x){ return x * x; }
template<class T> T gcd(T a, T b){ return b ? gcd(b, a%b) : a; }
template<class T> void read(T&num) {
    char CH; bool F=false;
    for(CH=getchar();CH<'0'||CH>'9';F= CH=='-',CH=getchar());
    for(num=0;CH>='0'&&CH<='9';num=num*10+CH-'0',CH=getchar());
    F && (num=-num);
}

const int N=1e6+10;

int n;
int prime[N];

void init(){
  for(int i = 2; i * i < N; i++)if(!prime[i]){
    for(int j = 2 * i; j < N; j += i)prime[j] = 1;
  }
}

int  main(){
  int T;
  read(T);
  init();
  while(T--){
    read(n);
    int ans = 2, num;
    for(int i = 2; i <= n; i++)if(!prime[i]){//素數
      int u = (int)(log(n) / log(i));
      int v = (int)pow(i, u);
      for (int j = 2; ; ++j)if (v * j > n){
        v *= j;
        break;
      }
      ans = max(ans, v);
    }
    printf("%d\n", ans);
  }
  return 0;
}

網上的題解:

假設有質數K,可以求出t,使得K的t次方剛好小於等於m(K^t<=m)那麼lcm(1,2,…,m)分解質因數中一定而且最多有t個質數K連乘,其實我們可以就是求的質數的最高次冪,這樣就可以很快地吧lcm(1,2,…,m)分解質因數那麼怎麼把 lcm(n+1,n+2,…,m)分解質因數呢仍然假設質數K,可以求出最大的t,以及一個常數c(1<=c < K),使得 n+1<=c*K^t<=m
那麼lcm(n+1,n+2,…,m)分解質因數中一定而且最多有t個質數K連乘。比如說質數3,n=16,m=22,可以求的c=2,t=2,即17<=2*3^2=18<=22,這樣lcm(17,18,19,20,21,22)中最多有2個質數3連乘既然知道怎麼求lcm(n+1,n+2,..,m)和lcm(1,2,..,m)了來探討一下怎麼求最小的m吧我們想讓這兩個lcm分解質因數後完全一樣,也就是說連乘的質數個數也完全相等。也就是說,對於每個質數K都可以滿足,存在c和最大的t 使得n+1<=c*K^t<=m對於大於n小於m的質數,我們假設是P,那麼一定n+1<=P<=m,一定可以滿足條件所以我們就只看小於等於n的質數就可以了因為要使每個小於N的質數K,都存在c和最大的t 使得n+1<=c*K^t<=m,我們列舉每一個質數,並求得c和t,使得剛好c*K^t>=n,
答案就取最大的c*K^t,即 max( c*K^t )這樣lcm(1,2,…,m)和lcm(n+1,n+2,…,m)的分解質因數後均至少有t個質數K。如果最終m有 k^(t+1)<=m,那麼這個K^(t+1)>n一定成立,故仍滿足條件

程式碼:

#include <bits/stdc++.h>
using  namespace  std;

template<class T> T sqr(T x){ return x * x; }
template<class T> T gcd(T a, T b){ return b ? gcd(b, a%b) : a; }
template<class T> void read(T&num) {
    char CH; bool F=false;
    for(CH=getchar();CH<'0'||CH>'9';F= CH=='-',CH=getchar());
    for(num=0;CH>='0'&&CH<='9';num=num*10+CH-'0',CH=getchar());
    F && (num=-num);
}

const int N=1e6+10;

int n;
int prime[N];

void init(){
  for(int i = 2; i * i < N; i++)if(!prime[i]){
    for(int j = 2 * i; j < N; j += i)prime[j] = 1;
  }
}

int  main(){
  int T;
  read(T);
  init();
  while(T--){
    read(n);
    int ans = 2, num;
    for(int i = 2; i <= n; i++)if(!prime[i]){//素數
      for(num = i; num <= n/i; num *= i)  ;

      ans = max(ans, (n / num + 1) * num);  
    }
    printf("%d\n", ans);
  }
  return 0;
}