链接:http://acm.neu.edu.cn/hustoj/problem.php?id=1694
题意:给定多个n,求LCM(1~n)/pi{pi为1~n中的素数}。
分析:因为n太大有10^14,我们得观察一些性质才行。因为要求的是最小公倍数然后除掉所有的质数,这里很明显大于sqrt(n)的素数就没意义了,因为最后答案中留下的只能是指数大于1的素数。那么我们就将素数范围缩小到了10^7,然后我们再来看看有什么其他的性质,我们会知道素数p在答案中的贡献应该是p^k<=n<p^(k+1)时的p^(k-1),并且明显会有小质数的贡献质数k>=大质数的k,有了这些我们就能处理出2^2,2^3,3^3等等这些数了,比如:(4,2),(8,2),(9,3),(16,2),(25,5)。。。假设n=10,那我们找到小于它的第一个值(9,3)那么答案就是2*2*3啦,当n=26时找到(25,5)答案就是2*2*3*2*5啦。详见代码。
代码:
#include<map> #include<set> #include<cmath> #include<queue> #include<bitset> #include<math.h> #include<cstdio> #include<vector> #include<string> #include<cstring> #include<iostream> #include<algorithm> #pragma comment(linker, "/STACK:102400000,102400000") using namespace std; const int N=10000010; const int MAX=1000000100; const int mod=100000000; const int MOD1=1000000007; const int MOD2=1000000009; const double EPS=0.00000001; typedef long long ll; const ll MOD=1000000007; const int INF=1000000010; typedef double db; typedef unsigned long long ull; struct node { ll x,y,z; node(){} node(ll x,ll y):x(x),y(y){} bool operator < (const node a) const{ return x<a.x; } }f[700000]; int g,a[N],q[N]; void deal(ll n) { int i,j,k=0; ll mul; memset(q,0,sizeof(q)); for (i=2;i<=n;i++) { if (!q[i]) a[++k]=i; for (j=1;j<=k;j++) { if ((ll)a[j]*i>n) break ; q[a[j]*i]=1; if (i%a[j]==0) break ; } } n=n*n; for (i=1;i<=k;i++) { mul=(ll)a[i]*a[i]; f[++g]=node(mul,a[i]); while (log(mul)+log(a[i])<=log(n)) { f[++g]=node(mul*a[i],a[i]);mul*=a[i]; } } sort(f+1,f+g+1);f[1].z=2ll; for (i=2;i<=g;i++) f[i].z=f[i-1].z*f[i].y%MOD; } ll getans(ll n) { if (n<4) return 1ll; if (n>=f[g].x) return f[g].z; int l=1,r=g,mid=(l+r)>>1; while (l+1<r) if (f[mid].x>n) { r=mid;mid=(l+r)>>1; } else { l=mid;mid=(l+r)>>1; } return f[l].z; } int main() { int i,t,ca; ll n,ans; deal(10000000ll); scanf("%d", &t); for (ca=1;ca<=t;ca++) { scanf("%lld", &n); printf("Case %d: %lld\n", ca, (getans(n)+MOD)%MOD); } return 0; }
时间: 2024-10-11 03:03:21