[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]签到题的主要内容,如果未能解决你的问题,请参考以下文章

T51658 wsy签到题

luogu2114 [NOI2014]起床困难综合症

真假签到题(签到+打表)

一道有趣的签到题

「Luogu P5368 [PKUSC2018]真实排名」

Inversion 多校签到题