【洛谷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;
}
posted @ 2020-10-16 07:15  stoorz  阅读(128)  评论(0编辑  收藏  举报