2021-06-04 20:38:05 星期五
约数个数:
首先讲解了一下约数个数,\(n=p_1^{a_1}p_2^{a_2}p_3^{a_3}.....p_k^{a_k}\),求n的正约数个数:
我们知道\(p_1,p_2....p_k\)是\(n\)的素数因子,除此之外就\(n\)没有其他素数因子了,那么我们可以知道\(n\)的因子必将是这些素数的排列组合,例如我们可以选出\(0,1,2,3,...a_1\)个\(p_1\)这有\((a_1+1)\)中选择,同理\(p_2,p_3.....p_k\)分别有\((a_2+1),(a_3+1),(a_4+1)...(a_k+1)\)种选择,然后我们知道他们互不影响所以用乘法原理得\(n\)的约数个数为:
这个挺重要的,能记就记住吧,最重要是理解,20年蓝桥杯好像用到这个知识点了.
欧拉函数
之后引进欧拉函数:小于n且与n互素的整数个数\(n=p_1^{a_1}p_2^{a_2}p_3^{a_3}.....p_k^{a_k}\)求小于n且与n互素的数的个数.
首先我们要求与n互素的个数,那么换种思路,用容斥定理的思想来看,我们只需要用总数n减去\(p_1,p_2,....p_k\)的倍数的个数即可.即\(n-\frac{n}{p_1}-\frac{n}{p_2}-.....-\frac{n}{p_k}\),然后加上两个素数乘积的倍数的个数,(有点绕, 但是理解容斥定理,就肯定能懂)
然后经过公式的转化(比较难,作者也不太会)
就变成了我们常见的欧拉函数:
那么我们只需要求出小于n的素数,然后算一下即可,也可借助筛法,直接求出.我去翻翻我之前写的.(静等)等不及自己动手也可.
之后说一个例题:Send a Table
题意
给出你n让你求出共多少对gcd(i,j)==1,(i<=n,j<=n) 问你共多少对:(i,j)与(j,i)当(i!=j)时算两对.
思路:
其实这个就是欧拉函数的一个应用,直接求出\(phi(2)+phi(3)+...phi(n)\)乘以2+1即可.
为什么那,我们固定一个x吧,那么小于x的欧拉函数有\(phi(x)\)个同理反过来固定y就有\(phi(y)\)个最后加上1是因为(1,1); (当然也可以把1算上phi最后别忘了减1就行.)
ll phi[maxn];
void p(){
phi[1]=1;
for(int i=2;i<=50000;i++){
if(!a[i]){
vis[++cnt]=i;
phi[i]=i-1;
}
for(int j=1;j<=cnt&&vis[j]*i<=50000;j++){
a[i*vis[j]]=1;
if(i%vis[j]==0){
phi[i*vis[j]]=phi[i]*vis[j];
break;
}else {
phi[i*vis[j]]=phi[i]*(vis[j]-1);
}
}
}
for(int i=1;i<=50000;i++){
phi[i]+=phi[i-1];
}
}
void solve()
{
printf("%lld\n",phi[n]*2-1);
}