1. 程式人生 > >$[ Luogu 4626 ]$ 一道水題$ II$

$[ Luogu 4626 ]$ 一道水題$ II$

() init 常數 esc 因數 name tps printf 毫秒


\(\\\)

\(Description\)


求一個能被\([1,n]\) 內所有數整除的最小數字,並對 \(100000007\) 取模

  • \(N\in [1,10^8]\)

\(\\\)

\(Solution\)


一道卡常好題 好吧是我常數太大了

考慮將限制區間內所有數質因數分解,對每一個質因子\(i\)記錄下\(t_i\)表示,這個質因子在區間內任意一個數裏,出現的最高冪次,那麽答案就應該是每個質因子對應的最高冪之積。

質數可以線性篩 註意常數別寫醜了 ,考慮如何求每一個質數的最高次冪。考慮將上限\(N\)除掉一次質因數\(p_i\),得到的數就代表原來那些含\(p_i\)的數的個數。於是一直將\(N\)

\(p_i\)\(0\),那麽合法的除的次數就是最高冪次的指數。

然後我寫了個快速冪就\(T\)了......註意到叠代的同時是可以記錄這個最高次冪的結果的,所以可以去掉快速冪的\(log\)復雜度雖然只快了幾十毫秒依然卡著時限

\(\\\)

\(Code\)


#include<cmath>
#include<cstdio>
#include<cctype>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#define N 100000010
#define R register
#define mod 100000007ll
using namespace std;
typedef long long ll;

bool vis[N];
int n,prm[N>>3];

inline void init(int n){
  for(R int i=2;i<=n;++i){
    if(!vis[i]) prm[++prm[0]]=i;
    for(R int j=1,k;j<=prm[0]&&(k=prm[j]*i)<=n;++j){
      vis[k]=1; if(i%prm[j]==0) break;
    }
  }
}

inline ll qpow(ll x,ll t){
  ll res=1;
  while(t){
    if(t&1) (res*=x)%=mod;
    (x*=x)%=mod; t>>=1;
  }
  return res;
}

int main(){
  scanf("%d",&n); init(n);
  R ll tmp,res,ans=1;
  for(R int i=1;i<=prm[0];++i){
    tmp=(ll)n; res=1;
    while(tmp>=prm[i]) (res*=prm[i])%=mod,tmp/=prm[i];
    (ans*=res)%=mod;
  }
  printf("%lld\n",ans);
  return 0;
}

$[\ Luogu\ 4626\ ]$ 一道水題$\ II$