题目背景
这是一道签到题!
建议做题之前仔细阅读数据范围!
题目描述
我们定义一个函数:qiandao(x) 为小于等于 x 的数中,与 x 不互质的数的个数。
这题作为签到题,给出 l 和 r,求出:
i=l∑rqiandao(i)mod666623333
输入格式
一行两个整数,l、r。
输出格式
一行一个整数表示答案。
输入输出样例
输入 #1复制
233 2333
输出 #1复制
1056499
输入 #2复制
2333333333 2333666666
输出 #2复制
153096296
说明/提示
- 对于 30% 的数据,l,r≤103。
- 对于 60% 的数据,l,r≤107。
- 对于 100% 的数据,1≤l≤r≤1012,r−l≤106。
代码实现;
#include<iostream>
#include<cstdio>
using namespace std;
typedef long long ll;
const ll Mn=1e6+5;
const ll mod=666623333;
ll prime[Mn],l,r,phi[Mn],vis[Mn],pc,ans,a[Mn];
void getprime(){
for(ll i=2;i<Mn;i++){
if(a[i])
prime[pc++] = i;
for(ll j=0;j<pc && prime[j]*i<Mn;j++){
a[prime[j]*i]=false;
if(i%prime[j]==0)
break;
}
}
}
int main(){
scanf("%lld%lld" ,&l,&r);
for(int i=0;i<Mn;i++)a[i]=true;
getprime();
for(ll i=l;i<=r;i++){
vis[i-l]=i;
phi[i-l]=i;
}
for(ll i=0;i<pc && prime[i]*prime[i]<=r;i++){
ll p=prime[i],start=l;
if(l%p!=0){
start=l/p*p+p;
}
for(ll j=start;j<=r;j=j+p){
phi[j-l]=phi[j-l]/p*(p-1);
while(vis[j-l]%p==0)
vis[j-l]/=p;
}
}
for(ll i=l;i<=r;i++){
if(vis[i-l]>1){
//处理剩下的大因子,最多有一个超过根号r的因子。
phi[i-l]=phi[i-l]/vis[i-l]*(vis[i-l]-1);
}
ans=(ans+(i-phi[i-l]))%mod;
}
printf("%lld\n",ans);
return 0;
}