【洛谷P3601】签到题
题目
题目链接:https://www.luogu.com.cn/problem/P3601
我们定义一个函数:qiandao(x)为小于等于x的数中与x不互质的数的个数。
这题作为签到题,给出l和r,要求求\(\sum_{i=l}^r qiandao(i)~mod~666623333\)。
思路
先线性筛出 \(1\sim 10^6\) 的质数,然后计算他们对 \(l\sim r\) 的数的贡献即可。
注意当当 \(l\sim r\) 的数最后可能还会有一个大质因子,再补上贡献即可。
时间复杂度 \(O(n\log \log n+r-l)\)。
代码
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1000010,MOD=666623333;
ll ql,qr,ans,phi[N],num[N];
int m,prm[N];
bool v[N];
void findprm(int n)
{
for (int i=2;i<=n;i++)
{
if (!v[i]) prm[++m]=i;
for (int j=1;j<=m;j++)
{
if (i>n/prm[j]) break;
v[i*prm[j]]=1;
if (i%prm[j]==0) break;
}
}
}
int main()
{
findprm(N-10);
scanf("%lld%lld",&ql,&qr);
if ((ql+qr)&1LL) ans=((ql+qr)%MOD)*((qr-ql+1LL)/2LL%MOD)%MOD;
else ans=((ql+qr)/2LL%MOD)*((qr-ql+1LL)%MOD)%MOD;
for (ll i=ql;i<=qr;i++) phi[i-ql]=num[i-ql]=i;
for (int i=1;i<=m;i++)
for (ll j=((ql-1)/prm[i])*prm[i]+prm[i];j<=qr;j+=prm[i])
{
phi[j-ql]=phi[j-ql]/prm[i]*(prm[i]-1);
while (num[j-ql]%prm[i]==0) num[j-ql]/=prm[i];
}
for (ll i=ql;i<=qr;i++)
{
if (num[i-ql]>1) phi[i-ql]=phi[i-ql]/num[i-ql]*(num[i-ql]-1);
ans=(ans-phi[i-ql])%MOD;
}
printf("%lld",(ans%MOD+MOD)%MOD);
return 0;
}