hdu2824线性求(即求n内所有)欧拉函数值phi模板

 1与任何数互质
4和15互质,4 15都不是质数,但互质 即gcd(4,15)=1

#include<bits/stdc++.h>
#define inf 0x3f3f3f3f
typedef long long ll;
using namespace std;
const int maxn=3e6+7;
int p[220000],phi[maxn];
//欧拉线性筛通过唯一分解法删合数(min质数*剩余部分)12=2*6,通过质数2来删 
//线性筛基础上增加phi数组实现求n以内全部数的欧拉函数值 
void f(){
    int cnt=0;
    memset(phi,0,sizeof(phi);
    phi[1]=1;
	for(int i=2;i<=maxn-1;i++){
	//vis可舍去,直接phi初始化为0,若phi仍为0,说明还未访问 
		if(!phi[i]) {
			p[++cnt]=i;
			phi[i]=i-1; 
			//质数i的欧拉函数值为i-1	
		}
		//利用已有的cnt个质数,和i相乘产生合数删去,知道某个质数和i不互质跳出。轮到i+1 
		for(int j=1;j<=cnt&&i*p[j]<maxn-1;j++){
			//i是p[j]的倍数 。实现线性O(n)的关键 
			if(i%p[j]==0){
				phi[i*p[j]]=phi[i]*p[j];
				break;
			}
			//i和p[j]互质 
			phi[i*p[j]]=phi[i]*(p[j]-1);
		}
	}
}

int main(){
  	int a,b;
	ll ans;
	//1的欧拉函数值为1.欧拉函数值即1~n内有多少个数和n互质
	memset(vis,0,sizeof(vis)); 
  	f();
	while(~scanf("%d%d",&a,&b)){
		ans=0; 
		for(int i=a;i<=b;i++)
			ans+=phi[i]; 
		cout<<ans<<endl;
	}     
    return 0;
}
/*由于多个数组,且最终值要存在ll里,如果开一个数组专门存前缀和 或开一个ll数组 都会超内存。
所以就不用前缀和了,这样省点内存,也多不了多少时间 */ 

Guess you like

Origin blog.csdn.net/weixin_50904510/article/details/119841806