[Luogu] P4626 一道水题 II

---恢复内容开始---

题目描述

一天,szb 在上学的路上遇到了灰太狼。

灰太狼:帮我们做出这道题就放了你。
szb:什么题?
灰太狼:求一个能被 [1,n] 内所有数整除的最小数字,并对 100000007 取模。
szb:这题太水了,就让我小弟来做好了。

然后你就光荣的接受了这个任务。

输入输出格式

输入格式:

一行一个数 n。

输出格式:

一行一个数 ans。

数据范围

n <= 1e8

题目解析

真是凶残,1e8的数据

题目分析难度不大,很容易想到是求1~n的最小公倍数,但要求效率较高。

以1~7举例:

for(int i = 1;i <= 7;i++) {
    分解质因数(i);
    ans *= (i的各个质因数 - ans中已有的各个质因数) 
}

我用pri[i]表示i的质因数集合,ans[]表示ans是由哪些数相乘得到的。

i = 1时,不管

i = 2时,pri[2] = 2,ans[] = 1,所以ans *= 2

i = 3时,pri[3] = 3,ans[] = 1,2,所以ans *= 3

i = 4时,pri[4] = 2,2,ans[] = 1,2,3,此时ans里有一个i了,要成为4的最小公倍数只需要*2就可以了,ans[] = 1,2,2,3

……

枚举质数,int now = 1;while(质数*now <= n) 质数*now。

Code

#include<iostream>
#include<cstdio>
#include<bitset>
#include<cmath>
using namespace std;

const int MAXN = 1e8 + 5;
const int MAXM = 5761460;
const int p = 100000007;

int n,cnt;
long long ans;
int prime[MAXM];
bool notprime[MAXN];

inline void Prime_Sieve(int n) {
    notprime[1] = true;
    for(register int i = 2;i <= n;i++) {
        if(notprime[i] == 0) prime[++cnt] = i;
        for(register int j = 1;j <= cnt;j++) {
            if(prime[j] * i > n) break;
            notprime[prime[j]*i] = true;
            if(!(i%prime[j])) break;
        }
    }
}

int main() {
    scanf("%d",&n);
    Prime_Sieve(n);
    long long tmp;
    ans = 1;
    for(register int i = 1;i <= cnt;i++) {
        tmp = prime[i];
        while(tmp*tmp <= n) tmp *= tmp;
        while(tmp*prime[i] <= n) tmp *= prime[i];
        ans *= tmp % p;
        ans %= p;
    }
    printf("%lld\n",ans%p);
    return 0;
}

 

posted @ 2018-09-14 17:01  Floatiy  阅读(457)  评论(0编辑  收藏  举报