题意:
求 lcm(1,2,....n)
数据范围:
n≤108 , 104 组测试数据
思路:
L(2) = 1 * 2
L(3) = 1 * 2 * 3
L(4) = 1 * 2 * 3 * 2 // because 4 = 2^2
L(5) = 1 * 2 * 3 * 2 * 5
L(6) = 1 * 2 * 3 * 2 * 5 // 6 is not a perfect power of a prime
L(7) = ….
所以我们可以看出,计算lcm的时候,不断乘过去的时候,只有当乘数为素数的 整数 次幂时,才会增大答案,所以做法就很简单了!
预处理( 1−108 )素数的前缀积,二分找到这个答案,然后更新答案!
比如 x=10 的话, ans=2∗3∗5∗7 (素数前缀积)
然后用素数 2,3 来更新答案(注意大于 x√ 的素数是不会更新答案的),所以 ans=ans∗23−1∗32−1这样明显是不够的,MLE
首先是尝试去块处理前缀乘积,缩小内存,还是MLE
然后灵机一动,flag 数组这个改为 bitset 实现,因为bitset内部本质就是采用位图来搞的!终于AC!
代码:
#include <bits/stdc++.h>
using namespace std;
typedef unsigned int UI;
const int N = 1e8 + 10;
const int BASE = 100;
int cnt, prime[5761460];
bitset<N> flag;
UI f[5761460/BASE];
void init()
{
int i, j;
cnt = 0;
for(int i = 2;i < N;i ++)
{
if(!flag[i]) prime[cnt ++] = i;
for(j = 0;j < cnt && i * prime[j] < N;j ++) {
flag[i * prime[j]] = 1;
if(i % prime[j] == 0) break;
}
}
UI tmp = 1u;
f[0] = 1u;
for(int i = 0;i < cnt;i ++) {
tmp = tmp * (UI)prime[i];
if((i+1) % BASE == 0) f[(i+1)/BASE] = tmp;
}
}
int main()
{
int T, ca = 0;
scanf("%d", &T);
init();
while(T --)
{
int n;
scanf("%d", &n);
int p = lower_bound(prime, prime + cnt, n) - prime;
if(prime[p] > n) p --;
UI ans = f[(p + 1)/BASE];
for(int i = (p+1)/BASE * BASE;i <= p;i ++) ans = ans * (UI)prime[i];
for(int i = 0;1LL * prime[i] * prime[i] <= n;i ++)
{
int cnt = 0, tmp = n;
while(tmp >= prime[i]) cnt ++, tmp /= prime[i];
for(int j = 2;j <= cnt;j ++) ans = ans * (UI)prime[i];
}
printf("Case %d: %u\n", ++ca, ans);
}
return 0;
}