单个欧拉值模板,欧拉函数打表模板,素数和欧拉一起打表模板

计蒜客之例题1

在这里插入图片描述
在这里插入图片描述
题解:

——t 小 n 大,适合用单个求欧拉值模板

单求欧拉函数通式:

——求 x 的欧拉函数值

φ ( x ) = x * ( 1 - 1 / p1 ) * ( 1 - 1 / p2 ) * ( 1 - 1 / p3 ) * ( 1 - 1 / p4 ) … ( 1 - 1 / pn )

pi表示的是啥?

答:将 x 质因数拆分后,pi 表示拆分后不同质因数。

n 表示 x 进行拆分后得到的不同质因数的个数,不用管具体是几。

举个例子:

x = 20 = 2 * 2 * 5
n = 2(2和5)
p1 = 2 (质数2)
p2 = 5 (质数5)

注意:
φ ( 1 ) = 1.

时间复杂度:O(x)

代码:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll phi(ll n)
{
	ll i,rea=n;
	for(i=2;i*i<=n;i++)
	{
		if(n%i==0)
		{
			rea=rea-rea/i;//等价于rea * ( 1 - 1 / i )
			while(n%i==0)
				n/=i;
		}
	}
	if(n>1)	rea=rea-rea/n;
	return rea;
}
void solve()
{
	ll n;
	scanf("%lld",&n);
	printf("%lld\n",phi(n));
}
int main()
{
	int T;
	scanf("%d",&T);
	while(T--)	solve();
	return 0;
}

计蒜客之例题2

题意不变,范围变化了

在这里插入图片描述
题解:

——t 大 n 小,适合打表模板

如何理解打表模板:

——注意看通式中的它:
( 1 - 1 / pi ) = ( pi - 1) / pi.【pi 为素数】

——接下来运用素数筛的思维模式:
找到素数 i ,遍历 i 的倍数,根据欧拉函数通式,被找的倍数是一定要乘一次 ( i - 1) / i 的。

代码1:欧拉函数打表(类似埃氏筛)

#include<bits/stdc++.h>
using namespace std;
const int MAXN=1e6;
int phi[MAXN+1];
void getEuler()
{
	memset(phi,0,sizeof(phi));
	phi[1]=1;//1的欧拉值为1 
	for(int i=2;i<=MAXN;i++)
	{
		if(!phi[i])
		{
			for(int j=i;j<=MAXN;j+=i)
			{
				if(!phi[j])	phi[j]=j;
				phi[j]=phi[j]/i*(i-1);
			}
		}
	}
}
void solve()
{
	int n;
	scanf("%d",&n);
	printf("%d\n",phi[n]);
}
int main()
{
	getEuler();
	int T;
	scanf("%d",&T);
	while(T--)	solve();
	return 0;
}

代码2:素数和欧拉一起打表的模板(线性筛)

//求1e6以内的素数和欧拉函数
#include<bits/stdc++.h>
using namespace std;
const int MAXN=1e6;
int book[MAXN+1],prime[MAXN+1],cnt;
int phi[MAXN+1];
void getPrimeEuler()
{
	cnt=0;
	memset(book,0,sizeof(book));
	book[0]=book[1]=1;
	phi[1]=1;
	for(int i=2;i<=MAXN;i++)
	{
		if(!book[i])
		{
			prime[++cnt]=i;
			phi[i]=i-1;
		}
		for(int j=1;j<=cnt&&prime[j]<=MAXN/i;j++)
		{
			book[i*prime[j]]=1;
			if(i%prime[j]==0)
			{
				phi[i*prime[j]]=phi[i]*prime[j];
				break; 
			}
			else
				phi[i*prime[j]]=phi[i]*phi[prime[j]];
		}
	}
}
void solve()
{
	int n;
	scanf("%d",&n);
	printf("%d\n",phi[n]);
}
int main()
{
	getPrimeEuler();
	int T;
	scanf("%d",&T);
	while(T--)	solve();
	return 0;
}
/*
有三条特性:
若a为质数   phi[a]=a-1;
若a为质数,b%a==0    phi[a*b]=phi[b]*a;
若a b互质  ph[a*b]=phi[a]*phi[b](当a为质数  如果b%a!=0) 
*/

拓展题1之[NOI2002]Robot 点击题解

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值