[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; }
所有博文均为原创 转载请留言征得博主同意