洛谷P3601 签到题
本文版权归ljh2000和博客园共有,欢迎转载,但须保留此声明,并给出原文链接,谢谢合作。
本文作者:ljh2000
作者博客:http://www.cnblogs.com/ljh2000-jump/
转载请注明出处,侵权必究,保留最终解释权!
题目链接:P3601
正解:线性筛+欧拉函数
解题报告:
我一看到这道题的第一反应居然是杜教筛,真是没救了…
显然答案就是每个数自己-他的欧拉函数,这个东西的和。
考虑区间范围不大,那么我们没必要把$[1,r]$整个区间的欧拉函数做出来。
因为大于$\sqrt{r}$的的质因子最多一个,那么我就可以把$10^6$范围内的质数筛出来,然后对$[l,r]$根据欧拉函数定义暴力算函数值。
最后再单独考虑$>$ $\sqrt{r}$的那个质因子的贡献。
这个复杂度就是$O(\sqrt{r}log(r-l))$。
//It is made by ljh2000 //有志者,事竟成,破釜沉舟,百二秦关终属楚;苦心人,天不负,卧薪尝胆,三千越甲可吞吴。 #include <iostream> #include <cstdlib> #include <cstring> #include <cstdio> #include <cmath> #include <algorithm> #include <ctime> #include <vector> #include <queue> #include <map> #include <set> #include <string> #include <complex> #include <bitset> using namespace std; typedef long long LL; typedef long double LB; typedef complex<double> C; const double pi = acos(-1); const int MAXN = 1000011; const int mod = 666623333; int m,prime[MAXN],cnt; bool vis[MAXN]; LL l,r,lb,rb,len,a[MAXN],R[MAXN],ans; inline LL getint(){ LL w=0,q=0; char c=getchar(); while((c<'0'||c>'9') && c!='-') c=getchar(); if(c=='-') q=1,c=getchar(); while (c>='0'&&c<='9') w=w*10+c-'0',c=getchar(); return q?-w:w; } inline void init(){ m=1000000; for(int i=1;i<=len;i++) a[i]=R[i]=l+i-1; for(int i=2;i<=m;i++) { if(!vis[i]) { prime[++cnt]=i; } for(int j=1;j<=cnt && i*prime[j]<=m;j++) { vis[i*prime[j]]=1; if(i%prime[j]==0) break; } } } inline void work(){ l=getint(); r=getint(); len=r-l+1; init(); LL now,pos; for(int i=1;i<=cnt;i++) { lb=l/prime[i]; rb=r/prime[i]; if((LL)prime[i]*lb<l) lb++; for(LL j=lb;j<=rb;j++) { now=(LL)prime[i]*j; pos=now-l+1; a[pos]/=prime[i]; a[pos]*=prime[i]-1; while(R[pos]%prime[i]==0) R[pos]/=prime[i]; } } for(int i=1;i<=len;i++) if(R[i]!=1) a[i]/=R[i],a[i]*=R[i]-1; for(int i=1;i<=len;i++) ans+=l+i-1-a[i],ans%=mod; printf("%lld",ans); } int main() { work(); return 0; } //有志者,事竟成,破釜沉舟,百二秦关终属楚;苦心人,天不负,卧薪尝胆,三千越甲可吞吴。
本文作者:ljh2000
作者博客:http://www.cnblogs.com/ljh2000-jump/
转载请注明出处,侵权必究,保留最终解释权!