luoguP3601 签到题 质因数分解+欧拉函数

题不难,但是求欧拉函数的部分要注意一下:

求欧拉函数的时候是没有必要取模的,因为一定能除开.   

如果取模的话由于出题人没有保证存在逆元会出现错误.   

由于 $[L,R]$ 区间大小不超过 $10^6$,然后每个数最多只有一个大于根号 R 的质因子,所以可以筛出来 $10^6$ 

以内的质因数,然后调和级数来更新答案. 

code:     

#include <bits/stdc++.h>    
#define N 1000009   
#define ll long long 
#define mod 666623333  
#define setIO(s) freopen(s".in","r",stdin) 
using namespace std;     
ll L,R;     
bool vis[N];  
vector<int>g[N];
int prime[N],inv[N],cnt;    
ll qpow(ll x,ll y) 
{   
    ll tmp=1;  
    for(;y;y>>=1,x=x*x%mod) if(y&1) tmp=tmp*x%mod;  
    return tmp;   
}
ll INV(ll x) { return qpow(x,mod-2);  }   
void init() 
{    
    for(int i=2;i<N;++i) 
    {
        if(!vis[i]) prime[++cnt]=i;  
        for(int j=1;j<=cnt&&prime[j]*i<N;++j) 
        {
            vis[i*prime[j]]=1;  
            if(i%prime[j]==0) break;  
        }
    }     
    inv[1]=1;    
    for(int i=2;i<N;++i) inv[i]=(ll)(mod-mod/i)*inv[mod%i]%mod;   
}
ll U(ll x,ll y) { return x%y==0?x/y:x/y+1;}
int main() 
{ 
    // setIO("input");  
    scanf("%lld%lld",&L,&R);          
    init();      
    for(int i=1;i<=cnt;++i)  
    {
        if(1ll*prime[i]*prime[i]>R) break;       
        for(ll j=U(L,prime[i])*1ll*prime[i];j<=R;j+=prime[i]) 
            g[j-L+1].push_back(prime[i]);          
    }   
    ll fin=0;   
    for(int i=1;i<=R-L+1;++i) 
    {        
        ll cur=1ll*i+L-1;  
        ll an=cur;     
        for(int j=0;j<g[i].size();++j) 
        {                 
            an=an/g[i][j]*(g[i][j]-1); 
            while((cur%g[i][j])==0) cur/=g[i][j];        
        }       
        if(cur>1) an=an/cur*(cur-1);             
        (fin+=1ll*i+L-1+mod-an)%=mod;  
    }   
    printf("%lld\n",fin);   
    return 0; 
}

  

 

posted @ 2020-06-16 15:19  EM-LGH  阅读(170)  评论(0编辑  收藏  举报