NEU 1694 Primorial vs LCM 【数学】

链接:http://acm.neu.edu.cn/hustoj/problem.php?id=1694

题意:给你一个N,让你LCM(1,2,3,...,N)除以N以内所有质数的积。

分析:我们知道这个LCM是N以内的所有质数最高次幂的积。

N<10e14,所以最大的素数不超过10e7,因为最大的质素不超过2次方,一次幂的会被除掉。

这里只剩下质数幂的积形式,所以每次只要碰到质数的幂就乘以这个质数。

我们可以预处理每个质数的幂,存下这个质数和它的幂,排个序后,我们可以连乘预处理上面所说的积改变过程。

然后二分求出小于N的最小质数的幂是第几个。

代码:

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<string>
#include<vector>
#include<queue>
#include<cmath>
#include<stack>
#include<set>
#include<map>
#define INF 0x3f3f3f3f
#define Mn 10000000
#define Mm 670000
#define MM 1e14+5
#define mod 1000000007
#define CLR(a,b) memset((a),(b),sizeof((a)))
#define CPY(a,b) memcpy ((a), (b), sizeof((a)))
#pragma comment(linker, "/STACK:102400000,102400000")
#define ul u<<1
#define ur (u<<1)|1
using namespace std;
typedef long long ll;
int prime[Mm],tot=0,no[Mn];
int a;
vector<pair<ll,int> > vt;
int ans[Mn];
void Prime() {
    vt.push_back(make_pair(1,1));
    for(int i=2;i<=Mn;i++) {
        if(!no[i]) {
            prime[++tot]=i;
            for(double j=(double)i*i;j<MM;j*=i)
                vt.push_back(make_pair((ll)j,i));
        }
        for(int j=1;prime[j]*i<=Mn;j++) {
            no[prime[j]*i]=1;
            if(i%prime[j]==0) break;
        }
    }
    sort(vt.begin(),vt.end());
    ans[0]=1;
    for(int i=1;i<vt.size();i++) {
        ans[i]=((ll)ans[i-1]*vt[i].second)%mod;
    }
}
int main() {
    Prime();
    int t;
    scanf("%d",&t);
    for(int cas=1;cas<=t;cas++) {
        ll n;
        scanf("%lld",&n);
        int l=0,r=vt.size()-1;
        while(l<r) {
            int mid=(l+r+1)>>1;
            if(vt[mid].first<=n) {
                l=mid;
            } else r=mid-1;
        }
        printf("Case %d: %d\n",cas,ans[l]);
    }
}


你可能感兴趣的:(NEU 1694 Primorial vs LCM 【数学】)