数学:洛谷P3601 签到题

原题传送门

数据上看显然从rl10e6下手

先筛法筛出素数

 再由欧拉函数

φ(n)=n*(1-1/p1)(1-1/p2)(1-1/p3)*(1-1/p4)……(1-1/pn)

用根号r以内质数的筛出[l,r]所有数的欧拉函数即可

注意做个标记,没被质数筛过的[l,r]中的数就是大质数,此时φ(n)=n-1

#include<bits/stdc++.h>
#define N 1000006
#define M 1000000000000
#define mod 666623333
long long p[N],a[N],vis[N];
bool prime[N];
using namespace std;
int main(){
    long long n,i,j,d,l,r,rr,x,s,ans,t;
    cin>>l>>r;rr=sqrt(r);d=r-l;
    for(i=0;i<=N-6;i++){prime[i]=true;vis[i]=i+l;}
    prime[1]=false;
    for(i=2;i<=rr;i++){
        if(prime[i]){
            for(j=i;j*i<=rr;j++){
                prime[j*i]=false;
            }
        }
    }
    n=0;
    for(i=2;i<=rr;i++){
        if(prime[i]) p[++n]=i;
    }
    for(i=0;i<=d;i++)a[i]=i+l;
    for(i=1;i<=n;i++){
        for(j=(l-1)/p[i]+1;j*p[i]<=r;j++){
            t=j*p[i];
            while(vis[t-l]%p[i]==0) vis[t-l]/=p[i];
            if(t>=l && t<=r) a[t-l]=a[t-l]*(p[i]-1)/p[i];
        }
    }
    for(i=0;i<=d;i++) if(vis[i]>1) a[i]=a[i]/vis[i]*(vis[i]-1);
    ans=0;
    for(i=0;i<=d;i++){
//        printf("%d:%d\n",l+i,a[i]);
        ans+=(i+l-a[i]);ans=(ans+mod)%mod;
    }
    cout<<ans;
    return 0;
}

 

posted @ 2021-11-09 23:48  遥望未来weilai  阅读(62)  评论(0)    收藏  举报