---恢复内容开始---
题目描述
一天,szb 在上学的路上遇到了灰太狼。
灰太狼:帮我们做出这道题就放了你。
szb:什么题?
灰太狼:求一个能被 [1,n] 内所有数整除的最小数字,并对 100000007 取模。
szb:这题太水了,就让我小弟来做好了。
然后你就光荣的接受了这个任务。
输入输出格式
输入格式:
一行一个数 n。
输出格式:
一行一个数 ans。
数据范围
n <= 1e8
题目解析
真是凶残,1e8的数据
题目分析难度不大,很容易想到是求1~n的最小公倍数,但要求效率较高。
以1~7举例:
for(int i = ;i <= ;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 + ;
const int MAXM = ;
const int p = ; int n,cnt;
long long ans;
int prime[MAXM];
bool notprime[MAXN]; inline void Prime_Sieve(int n) {
notprime[] = true;
for(register int i = ;i <= n;i++) {
if(notprime[i] == ) prime[++cnt] = i;
for(register int j = ;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 = ;
for(register int i = ;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 ;
}