(一点都不签到的)签到题
题目背景
这是一道签到题!
建议做题之前仔细阅读数据范围!
题目描述
我们定义一个函数:qiandao(x)为小于等于x的数中与x不互质的数的个数。
这题作为签到题,给出l和r,要求求∑i=lrqiandao(i) mod 666623333。
输入输出格式
输入格式:
一行两个整数,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。
先筛出来1e6以内素数 然后质因数分解一波 用欧拉函数公式算 用质数去筛倍数(O(n*1/i(i为素数))约等于O(nlogn)) 不要用每一个倍数枚举质数来判断(O(n*素数个数)约等于O(n))最后剩下的一定是大素数 直接计算
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
const int maxn=1000000+10;
bool vis[maxn];
typedef long long ll;
const ll MOD=666623333;
ll phi[maxn];
ll now[maxn];
ll pri[maxn];
ll ps;
inline void get_prime(){
for(ll i=2;i<=1000000;i++){
if(!vis[i])
pri[++ps]=i;
for(ll j=1;j<=ps&&i*pri[j]<=1000000;j++){
vis[i*pri[j]]=1;
if(i%pri[j]==0)
break;
}
}
}
int main(){
//freopen("a.in","r",stdin);
//freopen("a.out","w",stdout);
ll l,r;
scanf("%lld %lld",&l,&r);
get_prime();
for(ll i=l;i<=r;i++)
phi[i-l+1]=i,now[i-l+1]=i;
for(ll i=1;i<=ps;i++){
ll p=pri[i];
if(p>r)
break;
ll k=l/p;
if(l%p!=0)
k++;
for(ll j=k*p;j<=r;j+=p){
phi[j-l+1]=(phi[j-l+1]/p);
phi[j-l+1]*=(p-1);
while(now[j-l+1]%p==0)
now[j-l+1]/=p;
}
}
ll ans=0;
for(ll i=l;i<=r;i++){
if(now[i-l+1]!=1)
phi[i-l+1]=phi[i-l+1]/now[i-l+1]*(now[i-l+1]-1);
ans+=i-phi[i-l+1];
ans%=MOD;
}
printf("%lld\n",ans);
return 0;
}