A 洛谷 P3601 签到题 [欧拉函数 质因子分解]

题目背景

这是一道签到题!

建议做题之前仔细阅读数据范围!

题目描述

我们定义一个函数:qiandao(x)为小于等于x的数中与x不互质的数的个数。

这题作为签到题,给出l和r,要求求

输入输出格式

输入格式:

 

一行两个整数,l、r。

 

输出格式:

 

一行一个整数表示答案。

 

输入输出样例

输入样例#1:
233 2333
输出样例#1:
1056499
输入样例#2:
2333333333 2333666666
输出样例#2:
153096296

说明

对于30%的数据,

对于60%的数据,

对于100%的数据,


 

比赛时傻逼了一直想用lp[]进行质因子分解可是空间不够

其实只要筛出sqrt(r)范围的质数就可以了

不能对每个数直接质因子分解 根号会T

所以用了管用伎俩 每个质数枚举[l,r]范围的倍数进行质因子分解 复杂度O(n~nlogn)

//
//  main.cpp
//  AA
//
//  Created by Candy on 2017/2/2.
//  Copyright © 2017年 Candy. All rights reserved.
//

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
typedef long long ll;
const int N=1e6+5,MOD=666623333;
inline ll read(){
    char c=getchar();ll x=0,f=1;
    while(c<'0'||c>'9'){if(c=='-')f=-1; c=getchar();}
    while(c>='0'&&c<='9'){x=x*10+c-'0'; c=getchar();}
    return x*f;
}
ll l,r;
bool notp[N];
int p[N];
void sieve(int n){//printf("%d\n",n);
    for(int i=2;i<=n;i++){
        if(!notp[i]) p[++p[0]]=i;
        for(int j=1;j<=p[0]&&i*p[j]<=n;j++){
            notp[i*p[j]]=1;
            if(i%p[j]==0) break;
        }
    }
}
ll phi[N],x[N];
void solve(){
    for(int i=1;i<=r-l+1;i++) x[i]=phi[i]=i+l-1;
    for(int i=1;i<=p[0];i++){
        ll lb=p[i]*(l/p[i]),rb=p[i]*(r/p[i]);//printf("hi %d %d %d %d\n",i,p[i],lb,rb);
        for(ll j=lb;j<=rb;j+=p[i]) if(j>=l){
            phi[j-l+1]=phi[j-l+1]/p[i]*(p[i]-1);
            while(x[j-l+1]%p[i]==0) x[j-l+1]/=p[i];
        }
    }
    for(int i=1;i<=r-l+1;i++) if(x[i]>1) phi[i]=phi[i]/x[i]*(x[i]-1);
    //for(int i=1;i<=r-l+1;i++) printf("phi %d %lld\n",i+l-1,phi[i]);
}
ll ans;
int main(int argc, const char * argv[]){
    l=read();r=read();
    sieve(sqrt(r)+1);
    solve();
    for(ll i=1;i<=r-l+1;i++) (ans+=i+l-1-phi[i])%=MOD;
    printf("%lld",ans);
    return 0;
}

 

posted @ 2017-02-02 12:05  Candy?  阅读(455)  评论(0编辑  收藏  举报