#include <map> #include <stack> #include <queue> #include <cmath> #include <vector> #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #define ll long long using namespace std; const int maxn=1e8+10; const int maxm=6e6+10; int cnt=0; int prime[maxm]; int vis[(maxn>>5)+10]; unsigned int sum[maxm]; void set_bit(int x) { vis[x>>5] |= (1<<(x%32)); } bool check_bit(int x) { return vis[x>>5] & (1<<(x%32)); } void get_prime() { int side=sqrt(maxn+0.5); for(int i=2;i<=side;i++) { if(!check_bit(i)) { prime[++cnt]=i; for(int j=i*i;j<=maxn;j+=i) { set_bit(j); } } } for(int i=side+1;i<=maxn;i++) { if(!check_bit(i)) { prime[++cnt]=i; } } } void Init() { sum[0]=1; for(int i=1;i<=cnt;i++) { sum[i]=sum[i-1]*prime[i]; } } int main() { int T,n; scanf("%d",&T); get_prime(); Init(); for(int k=1;k<=T;k++) { scanf("%d",&n); int p=upper_bound(prime+1,prime+cnt+1,n)-prime-1; unsigned ans=sum[p]; for(int i=1;i<=cnt&&prime[i]*prime[i]<=n;i++) { int mul=prime[i]; int tmp=prime[i]*prime[i]; while(tmp/mul==prime[i]&&tmp<=n) { tmp*=prime[i]; mul*=prime[i]; } ans*=(mul/prime[i]); } printf("Case %d: %u\n",k,ans); } return 0; }
用位图进行素数筛,节省空间。
unsigned int 自动取余(2的32次方)
记录素数的前缀积,然后进行计算
求法
L(1) = 1 L(x+1) = { L(x) * p if x+1 is a perfect power of prime p { L(x) otherwise