标签:
链接:戳这里
题意:求出LCM(1~n)/(年以内的素数乘积)
思路:LCM(1~n) = n以内的每个素数的能取的最高次幂的乘积
LCM(1,2,3,4,,,49) = 2^5 * 3^3 * 5^2 * 7^2 * 11 *13...
发现LCM(1~49) 除一下 49以内的素数 = 2^4 * 3^3 * 5 * 7
这样只需要计算1e7以内的素数然后取每个素数的最高次幂-1,就可以求出n=1e14的情况 但是还是会T
由于一段连续的n的答案是一样的 所有来模拟一下过程 (这里的结论是没有当出现一个新的最高次幂的素数的时候才会改变LCM的值
2 1
3 1
4 2
8 4
9 12
16 24
25 120
prime^num anw[上一项]*prime
下面来分析分析
想一下这是什么原因呢 因为每次只有得到新的prime得最高次幂才会对LCM产生变化
所以每次的答案更新也就在prime^num这里
哎 没意思 然后在线性筛那里记录值 然后二分输出答案
代码:
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<string> #include<vector> #include <ctime> #include<queue> #include<set> #include<map> #include<stack> #include<iomanip> #include<cmath> #define mst(ss,b) memset((ss),(b),sizeof(ss)) #define maxn 0x3f3f3f3f #define MAX 10000005 ///#pragma comment(linker, "/STACK:102400000,102400000") typedef long long ll; typedef unsigned long long ull; using namespace std; const ll INF=1e14+5; #define mod 1000000007 int T,cas; vector< pair<ll,int> > V; vector<ll> anw; int vis[MAX],prime[MAX]; void init(){ int cnt=0; V.push_back(make_pair(1LL,1)); for(int i=2;i<=MAX;i++){ if(!vis[i]){ prime[cnt++]=i; for(double j=(double)i*i;j<INF;j*=i){ V.push_back(make_pair((ll)j,i)); } } for(int j=0;j<cnt;j++){ if((ll)i*prime[j]>MAX) break; vis[i*prime[j]]=1; if(i%prime[j]==0) break; } } sort(V.begin(),V.end()); anw.push_back(1LL); for(int i=1;i<V.size();i++){ anw.push_back((ll)V[i].second*anw[i-1]%mod); } } ll n; int main(){ init(); scanf("%d",&T); for(int cas=1;cas<=T;cas++){ scanf("%lld",&n); int l=0,r=V.size()-1,mid,ans=0; while(l<r){ mid=(l+r+1)/2; if(V[mid].first<=n) { l=mid; ans=mid; } else r=mid-1; } printf("Case %d: %lld\n",cas,anw[r]%mod); } return 0; }
标签:
原文地址:http://blog.csdn.net/libin66/article/details/51364142