这个题数字可真大啊 一直到 10^8
开始的时候素数都不敢筛
本题学到。。。压缩空间筛素数。其实也很简单用1位表示这个数是否是素数。
一个 int 是4个字节,有32位可以装32个数这样内存就压缩了32倍,这个数字还是挺大的。毕竟也 2^5 呢。
具体写法(判断和设置)
const int mask=1+2+4+8+16;
int isprim(int a)
{
return ((1<<(a&mask))&noprim[a>>5])==0;
}
void setbit(int a)
{
noprim[a>>5]|=(1<<(a&mask));
return ;
}
a&mask 是a%32, a>>5 是a/32
然后素数筛可以这么玩。。完全不管偶数,从3开始筛,每次加2,选倍数的时候也从3开始,每次加2。筛素数晒到 n^1/2 就可以了 10^8 只要筛掉 10000 一下质数的倍数就行了。
void getPrim()
{
data[0]=2;
cnt=1;
prim[0]=2;
int most=sqrt(MAX)+1;
for(int i=3;i<MAX;i+=2)
{
if(isprim(i))
{
data[cnt]=data[cnt-1]*i;
prim[cnt]=i;
cnt++;
for(int j=3*i;i<=most&&j<MAX;j+=2*i)
setbit(j);
}
}
}
然后本题的 trick。
1..n 的 lcm 首先小于他的素数都得乘一遍这个都能想到。还有就是想 4 8 9 这样的情况。
所以,本题的答案就是所有小于n的质数在 1...n 中出现的最高次幂的乘积。
#include <stdio.h>
#include <iostream>
#include <queue>
#include <algorithm>
#include <map>
#include <vector>
#include <cmath>
#include <string.h>
#include <stdlib.h>
#include <time.h>
#include <fstream>
#include <set>
#include <stack>
using namespace std;
#define READ freopen("acm.in","r",stdin)
#define WRITE freopen("acm.out","w",stdout)
#define ll long long
#define ull unsigned long long
#define PII pair<int,int>
#define PDI pair<double,int>
#define PDD pair<double,double>
#define MII map<int,int>::iterator
#define fst first
#define sec second
#define MS(x,d) memset(x,d,sizeof(x))
#define INF 0x3f3f3f3f
#define ALL(x) x.begin(),x.end()
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define ROOT 0,n-1,1
#define PB push_back
#define FOR(a,b,c) for(int a=b;a<c;a++)
#define MOD 1000000007
#define keyTree (ch[ ch[root][1] ][0])
#define MAX 100000003
int noprim[MAX/32+200];
int prim[5800000];
unsigned int data[5800000];
int cnt=0;
const int mask=1+2+4+8+16;
int isprim(int a)
{
return ((1<<(a&mask))&noprim[a>>5])==0;
}
void setbit(int a)
{
noprim[a>>5]|=(1<<(a&mask));
return ;
}
void getPrim()
{
data[0]=2;
cnt=1;
prim[0]=2;
int most=sqrt(MAX)+1;
for(int i=3;i<MAX;i+=2)
{
if(isprim(i))
{
data[cnt]=data[cnt-1]*i;
prim[cnt]=i;
cnt++;
for(int j=3*i;i<=most&&j<MAX;j+=2*i)
setbit(j);
}
}
}
unsigned int deal(ll a)
{
int p=upper_bound(prim,prim+cnt,a)-prim-1;
unsigned ans=data[p];
for(int i=0;1LL*prim[i]*prim[i]<=a;i++)
{
for(ll j=1LL*prim[i]*prim[i];j<=a;j*=(1LL*prim[i]))
ans*=prim[i];
}
return ans;
}
int main()
{
getPrim();
int cas;
scanf("%d",&cas);
for(int T=1;T<=cas;T++)
{
int a;
scanf("%d",&a);
printf("Case %d: %u\n",T,deal(a));
}
return 0;
}