2019.10.02日常总结兼洛谷P3601题解

洛谷 P 3601 : P3601: P3601:

【题意】: q i a n d a o ( x ) qiandao(x) qiandao(x)为小于等于 x x x且与 x x x 不互质 的数的个数,求 ∑ i = 1 n q i a n d a o ( i ) \sum _{i=1}^{n} qiandao(i) i=1nqiandao(i) m o d mod mod 666623333 666623333 666623333
【思路】: 首先,有一个很显然的结论: q i a n d a o ( i ) = i − τ ( i ) qiandao(i) = i - \tau (i) qiandao(i)=iτ(i),其中 τ ( i ) \tau(i) τ(i)表示小于等于 i i i且与 i i i 互质的数的个数
那么原问题被我们转化为了求 ∑ i = 1 n ( i − τ ( i ) ) \sum _{i=1} ^ n (i- \tau(i)) i=1n(iτ(i)) m o d mod mod 666623333 666623333 666623333
考虑到 l , r l,r l,r很大,但 r − l ≤ 1 × 1 0 6 r-l \leq 1 \times 10 ^ 6 rl1×106,所以我们求 1 − r 1-\sqrt r 1r 中的质数,然后根据它们来求解
【代码】:

#include 
using namespace std;
const int N=1e6+1e3;
int prime[N],tot;
bool is_prime[N];
inline void get_prime(int n){
	memset(is_prime,true,sizeof(is_prime));
	is_prime[0]=is_prime[1]=false;tot=0;
	for(int i=2;i<=n;i++)
	if (is_prime[i]){
		prime[++tot]=i;
		for(int j=i;j<=n/i;j++)
		is_prime[i*j]=false;
	}
}//埃式筛
long long n,m,f[N],p[N];
long long i,j,pri,x,ans;
const long long mod=666623333;
int main(){
	cin>>n>>m;
	get_prime(1000000);
	for(i=n;i<=m;i++)
	f[i-n]=p[i-n]=i;
//	技巧:通过让i减n达到把所有数字左移的效果,从而减少空间的浪费
	for(i=1;i<=tot;i++)
	for(pri=prime[i],j=max(2ll,(n-1)/pri+1)*pri;j<=m;j+=pri){
		x=j-n;f[x]=f[x]/pri*(pri-1);//求小于等于i且与i互质的数的个数
		while (p[x]%pri==0) p[x]/=pri;//分解质因数
	}
	for(i=0;i<=m-n;i++){
		if (p[i]>1) f[i]=f[i]/p[i]*(p[i]-1);
		ans=(ans+i+n-f[i])%mod;
	}
	cout<<ans;
	return 0;
}

你可能感兴趣的:(原创)