[luogu3601]签到题
Posted sdzwyq
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[luogu3601]签到题相关的知识,希望对你有一定的参考价值。
[luogu3601]签到题
luogu
求[sum_{i=l}^ri-phi(i)]
一个朴素的想法是枚举l~r,根号求(phi),显然这样是((r-l)sqrt r),时间无法承受
考虑怎么优化求(phi)的时间,
我们知道对于一个数x,超过(sqrt x)的质因子最多只有一个
我们考虑对[l,r]的数开vector记录质因子
我们可以线筛求出(sqrt r)以内的质数,枚举它们的倍数放到相应的[l,r]的vector中
再枚举l~r求(phi)
这样时间和空间都是((r-l)logr)
#define ll long long
#include<bits/stdc++.h>
using namespace std;
const int _=1000005;
int mx,cnt,p[100000];
ll l,r,ans;
bool vis[_];
vector<int>v[_];
int main(){
cin>>l>>r;mx=sqrt(r);
for(int i=2;i<=mx;i++){
if(!vis[i])p[++cnt]=i;
for(int j=1;j<=cnt&&p[j]*i<=mx;j++){
vis[p[j]*i]=1;if(i%p[j]==0)break;
}
}
for(int i=1;i<=cnt;i++){
ll k=ceil(1.0*l/p[i])*p[i];
while(k<=r)v[k-l].push_back(p[i]),k+=p[i];
}
for(int i=0;i<=r-l;i++){
ll x=i+l,phi=i+l;
for(int j=0,sz=v[i].size();j<sz;j++){
int k=v[i][j];
phi/=k;phi*=k-1;
while(x%k==0)x/=k;
}
if(x>1)phi/=x,phi*=x-1;
ans=(ans+i+l-phi)%666623333;
}
cout<<ans<<endl;
return 0;
}
以上是关于[luogu3601]签到题的主要内容,如果未能解决你的问题,请参考以下文章