继整除分块后的下一篇数论恶补……
参考资料
https://blog.csdn.net/weixin_43237242/article/details/97388834
跳转按钮
讲解证明 \color{#8af}\texttt{讲解证明} 讲解证明
经典例题 \color{#8af}\texttt{经典例题} 经典例题
欧拉函数就是 φ ( n ) \varphi(n) φ(n),表示小于 n n n 的正整数中与 n n n 互质的数的个数。
把 n n n 质因数分解,设
n = p 1 x 1 ⋅ p 2 x 2 ⋅ . . . ⋅ p k x k n=p_1^{x_1}\cdot p_2^{x_2}\cdot...\cdot p_k^{x_k} n=p1x1⋅p2x2⋅...⋅pkxk
因为 x < n x
φ ( n ) = ( 1 − 1 p 1 ) ( 1 − 1 p 2 ) . . . ( 1 − 1 p k ) = ∏ i = 1 k ( 1 − 1 p i ) = ∏ i = 1 k p i − 1 p i \varphi(n)=(1-\frac{1}{p_1})(1-\frac{1}{p_2})...(1-\frac{1}{p_k})=\prod\limits_{i=1}^k(1-\frac{1}{p_i})=\prod\limits_{i=1}^k\frac{p_i-1}{p_i} φ(n)=(1−p11)(1−p21)...(1−pk1)=i=1∏k(1−pi1)=i=1∏kpipi−1
这时求一个 φ ( n ) \varphi(n) φ(n) 的时间复杂度为 Θ ( n ) \Theta(\sqrt n) Θ(n)(有时候也有用的)。
code
//&Eular
lng Eular(lng n){
lng ans=n;
for(lng i=2;i*i<=n;i++)
if(n%i==0){
ans=ans/i*(i-1);
while(n%i==0) n/=i;//把i这个质因子除光
}
if(n>1) ans=ans/n*(n-1);
return ans;
}
很多时候要用到 φ ( 1 ) , φ ( 2 ) , . . . , φ ( n ) \varphi(1),\varphi(2),...,\varphi(n) φ(1),φ(2),...,φ(n),如果这样一个一个求时间复杂度就是 Θ ( n n ) \Theta(n\sqrt n) Θ(nn)。
但是,如果用类似筛质数的方法打表求 φ ( i ) \varphi(i) φ(i) 时间复杂度就可以到 Θ ( n 1 + n 2 + . . . n n ) = Θ ( n log n ) \Theta(\frac n1+\frac n2+...\frac nn)=\Theta(n\log n) Θ(1n+2n+...nn)=Θ(nlogn)。
code
//&Eular
const int N=1e5+10;
int E[N];
void Eular(lng n){
for(int i=2;i<=n;i++)if(!E[i])//说明i是质数
for(int j=i;j<=n;j+=i){
if(!E[j]) E[j]=j;
E[j]=E[j]/i*(i-1);
}
}
另外一种方法,求质数的同时求 φ ( i ) \varphi(i) φ(i)。
code
//&Eular
const int N=1e6+10;
int cnt,phi[N],p[N];
bool np[N];
void Eular(int n){
for(int i=2;i<=n;i++){
if(!np[i]) p[++cnt]=i,phi[i]=i-1;
for(int j=1;j<=cnt&&i*p[j]<=n;j++){
np[i*p[j]]=1;
if(i%p[j]==0){phi[i*p[j]]=phi[i]*p[j];break;}
else phi[i*p[j]]=phi[i]*(p[j]-1);
}
}
}
[Cnoi2020]明天后的幻想乡
有一个数列 { 1 , 2 , 3 , . . . , n } \{1,2,3,...,n\} {1,2,3,...,n}, 求它有多少个子序列是等比数列(至少 3 3 3 项,没有重复元素,无序),答案对 998244353 998244353 998244353 取模。
数据范围: 1 ≤ n ≤ 1 0 12 1\le n\le 10^{12} 1≤n≤1012。
等比数列 { a 1 , a 2 , . . . , a k } ( a 1 < a 2 < . . . < a k , k ≥ 3 ) \{a_1,a_2,...,a_k\}(a_1
∵ a k = a 1 ⋅ ( x y ) k − 1 \because a_k=a_1\cdot (\frac xy)^{k-1} ∵ak=a1⋅(yx)k−1
∴ a k y k − 1 = a 1 x k − 1 \therefore a_ky^{k-1}=a_1x^{k-1} ∴akyk−1=a1xk−1
x k − 1 ∣ a k , a 1 = a k ⋅ ( y x ) k − 1 x^{k-1}\mid a_k,a_1=a_k\cdot(\frac yx)^{k-1} xk−1∣ak,a1=ak⋅(xy)k−1
∵ k ≥ 3 , a k ≤ n , x k − 1 ∣ a k \because k\ge3,a_k\le n,x^{k-1}\mid a_k ∵k≥3,ak≤n,xk−1∣ak
∴ x = a k k − 1 ≤ n \therefore x=\sqrt[k-1]{a_k}\le\sqrt n ∴x=k−1ak≤n
然后可以 Θ ( n ) \Theta(\sqrt n) Θ(n) 枚举 x x x,然后再 Θ ( log n ) \Theta(\log n) Θ(logn) 枚举 k k k,然后就得到了 a k a_k ak 的数量为 ⌊ n x k − 1 ⌋ \lfloor\frac{n}{x^{k-1}}\rfloor ⌊xk−1n⌋。
得到 a k a_k ak 以后,因为 a 1 = a k ⋅ ( y x ) k − 1 a_1=a_k\cdot(\frac yx)^{k-1} a1=ak⋅(xy)k−1,而如果 x , y x,y x,y 不互质的话,就会有重复的等比数列。所以这里的 y y y 应该有 φ ( x ) \varphi(x) φ(x) 种。
然后就都解决了,注意要 m o d 998244353 \bmod 998244353 mod998244353。
code
#include
using namespace std;
//&Start
#define lng long long
const int inf=0x3f3f3f3f;
const lng Inf=1e17;
//&Eular
const int N=1e6+10;
int cnt,phi[N],p[N];
bool np[N];
void Eular(int n){ //当时还不知道有前面那种简单的方法
for(int i=2;i<=n;i++){
if(!np[i]) p[++cnt]=i,phi[i]=i-1;
for(int j=1;j<=cnt&&i*p[j]<=n;j++){
np[i*p[j]]=1;
if(i%p[j]==0){phi[i*p[j]]=phi[i]*p[j];break;}
else phi[i*p[j]]=phi[i]*(p[j]-1);
}
}
}
//&Main
const lng mod=998244353;
lng n,ans;//不开longlong见祖宗
int main(){
scanf("%lld",&n);
Eular(sqrt(n));
for(lng i=2;i*i<=n;i++){//i就是x
for(lng j=i*i;j<=n;j*=i)//j就是 i^(k-1)
(ans+=(n/j)%mod*phi[i])%=mod;
}
printf("%lld\n",ans);
return 0;
}
然后就结束了,我数论太蒻了。祝大家学习愉快!