数论函数筛法模板+TG的实用工具整理
数论函数筛法模板+TG的实用工具整理
标签(空格分隔):数论
本博客与数学定义共同使用效果更佳
目录
-
线性筛约数个数
-
求单个值的欧拉函数
-
线性筛欧拉函数
-
线性筛莫比乌斯函数
-
快速幂原理介绍
-
取模神器
线性筛约数个数
声明:借鉴 genshy 博客
对于每一个数都有唯一分解定理
维护两个数组
这个数的约数个数可以写为
1、当
对于性质
2、当
这里做一下解释说明:
首先,现行筛的终止条件是
继续看下一个,根据定义可以知道
3、当
void get_prime()
{
g[1]=1;
f[1]=1;
for(int i=2;i<=N-5;i++)
{
if(!check[i])
{
prime[++tot]=i;
g[i]=1;
f[i]=2;
}
for(int j=1;j<=tot&&i*prime[j]<=N-5;j++)
{
//最先枚举到的prime一定是这个数的最小质因子
check[i*prime[j]]=1;
if(i%prime[j]==0)
{
g[i*prime[j]]=g[i]+1;
//因为prime[j]可以整除i。
//说明当前prime[j]也是i的最小
//质因子
f[i*prime[j]]=f[i]*(g[i*prime[j]]+1)/(g[i]+1);
break;
}
else
{
g[i*prime[j]]=1;//因为最小质因子只有一个prime[j]
f[i*prime[j]]=f[i]*f[prime[j]];//积性函数
}
}
}
}
求单个值的欧拉函数
首先,根据唯一分解定理可得:
可以得到:
那么在OI中运算可以化为
void get_phi(int x)
{
phi=x;
int prime=x;
for(int i=2;i*i<=x;i++)
{
if(prime%i==0)
phi=phi/i*(i-1);
while(prime%i==0)
prime/=i;
}
if(prime>1)
phi=phi/prime*(prime-1);
}
线性筛欧拉函数
首先我们由定义知道
其次,根据积性函数的性质又可以知道
那么对于一个数
那么就可以推出如何线性筛欧拉函数了
void get_phi()
{
phi[1]=1;//
for(int i=2;i<=n;i++)
{
if(!vis[i])
{
prime[++cnt]=i;
phi[i]=i-1;
}
for(int j=1;j<=n&&prime[j]<=n/i;j++)
{
vis[i*prime[j]]=true;
if(i%prime[j]==0)
{
phi[i*prime[j]]=phi[i]*prime[j];
break;
}
else phi[i*prime[j]]=phi[i]*phi[prime[j]];
//互质直接用积性函数的性质
}
}
for(int i=1;i<=n;i++)
sum[i]=sum[i-1]+phi[i];
}
线性筛莫比乌斯函数
由定义可以知道
当一个数含有平方因子时,
当一个数为质数时,
根据这个性质就可以用线性筛来求莫比乌斯函数了
void get_mu()
{
mu[1]=1;
for(int i=2;i<=M;i++)
{
if(!vis[i])
prime[++cnt]=i,mu[i]=-1;
for(int j=1;j<=cnt&&prime[j]<=M/i;j++)
{
vis[i*prime[j]]=true;
if(i%prime[j]==0)
{
mu[i*prime[j]]=0;
break;
}
else
mu[i*prime[j]]=-mu[i];
}
}
}
快速幂原理介绍
听说过快速幂的应该都知道他可以在
首先快速幂是建立在二进制运算的基础上,其实我们可把次数看做是一个二进制数,就比如说
这个快速幂的原理其实就是把次数转换成二进制来进行加法运算。
只有在有
以上面的例子来说:
转换成二进制来看就是 :
由此可以看到其实就是一个实行次数二进制加法的过程,就可以快速求出一个次数巨大的数的值了qwq
int quick(int x,int p,int mod)//mod其实可以宏定义
{
//求 x^p%mod ;
int ret=1;
while(p)
{
if(p&1) ret=x*ret%mod;//遇到1了,进行二进制加法
x=x*x%mod;//实际上就是将次数<<1的过程
p>>=1;
}
return ret%mod;
}
取模神器
像我这种一遇到取模就头疼的孩子,自从有了这个就再也不怕了/cy
namespace Mod {
long long mul(long long a,long long b,long long mod) {
long long tmp = a * b - (long long)((long double)a * b / mod + 0.5) * mod;
return tmp < 0 ? tmp + mod : tmp;
}
int P;
void Build_Mod(int v) {P = v;}
inline int cH(long long x) {return (x % P + P) % P;}
int Pow_M(long long x, long long y) {long long ret = 1; x = cH(x);while (y) {if (y & 1) ret = mul(ret , x , P);x = mul(x , x , P), y >>= 1;}return cH(ret);}
int inv(long long x) {return Pow_M(x, P - 2);}
struct modint {
int x;
modint(int x = 0) : x(x) {}
modint operator = (const modint a) {x = a.x; return *this;}
modint operator = (const int a) {x = cH(a); return *this;}
};
inline modint operator + (modint a, modint b) {return modint(a.x + b.x >= P ? a.x + b.x - P : a.x + b.x);}
inline modint operator + (modint a, long long b) {return modint(cH((long long)a.x + b));}
inline modint operator - (modint a, modint b) {return modint(a.x < b.x ? a.x - b.x + P : a.x - b.x);}
inline modint operator - (modint a, long long b) {return modint(cH((long long)a.x - b));}
inline modint operator * (modint a, modint b) {return modint(mul(a.x , b.x , P));}
inline modint operator * (modint a, long long b) {return modint(cH(mul(a.x , b , P)));}
inline modint operator / (modint a, modint b) {return modint(mul(a.x , inv(b.x) , P));}
inline modint operator / (modint a, long long b) {return modint(mul(a.x , inv(b) , P));}
inline int operator == (modint a, modint b) {return a.x == b.x;}
inline modint operator += (modint &a, modint b) {a = a + b; return a;}
inline modint operator += (modint &a, long long b) {a = a + b; return a;}
inline modint operator -= (modint &a, modint b) {a = a - b; return a;}
inline modint operator -= (modint &a, long long b) {a = a - b; return a;}
inline modint operator *= (modint &a, modint b) {a = a * b; return a;}
inline modint operator *= (modint &a, long long b) {a = a * b; return a;}
inline modint operator /= (modint &a, modint b) {a = a / b; return a;}
inline modint operator /= (modint &a, long long b) {a = a / b; return a;}
inline istream & operator >> (istream &in, modint &a) {in >> a.x; return in;}
inline ostream & operator << (ostream &out, modint b) {out << b.x; return out;}
inline modint operator ^ (modint x, long long y) {return Pow_M(x.x, y);}
inline modint Ch(int x) {return modint(cH(x));}
inline void read(modint &x) {long long t; scanf("%lld", &t), x = t % P;}
inline void print(modint x) {printf("%d", x.x);}
inline void print(modint x, char c) {printf("%d%c", x.x, c);}
modint One = 1, Two = 2;
};