拾起,单位根的记忆
阶:
定义:
对于
a∈Z,
m∈N+ 且
a⊥m,满足
an≡1(modm) 的最小正整数
n 记为
δm(a)
约定:下列性质均在
a∈Z,
m∈N+ 且
a⊥m 的情况下研究
性质一:
a0,a1,a2,…,aδm(a)−1 模
m 互不相同
性质二:
an≡1(modm) 当且仅当
δm(a)∣n
性质三:
δm(ak)=gcd(δm(a),k)δm(a)
性质四:
gcd(δm(a),δm(b))lcm(δm(a),δm(b))∣δm(ab)∣lcm(δm(a),δm(b))
更为简单的形式:
δm(ab)=δm(a)δm(b)⟺δm(a)⊥δm(b)
性质五:
总存在
c,满足
δm(c)=lcm(δm(a),δm(b))
原根:
定义:
若存在
g 满足
δm(g)=φ(m),则称
g 为模
m 的原根
原根判定定理:
对于
m≥3 和
g⊥m,
g 是模
m 的原根当且仅当对于所有
p∣φ(m),都有
gpφ(m)≡1(modm)
原根个数定理:
模
m 的原根个数为
φ(φ(m))
原根存在定理:
模
m 的原根存在当且仅当
m=1,2,4,pe,2pe,其中
p 为奇质数且
e∈N+
求原根的算法:
从小到大逐一枚举并判断,直到找到原根
代码:
时间复杂度为
O(n41logn),可以找到所有原根
CPP#include<bits/stdc++.h>
using namespace std;
const int N=1000005;
typedef long long ll;
int T,cnt,phi[N],pri[N]; vector<int> factor,ans; bool vis[N];
void init(int n){
phi[1]=1;
for(int i=2;i<=n;i++){
if(!vis[i]) pri[++cnt]=i,phi[i]=i-1;
for(int j=1;j<=cnt&&i*pri[j]<=n;j++){
vis[i*pri[j]]=true;
if(i%pri[j]==0){
phi[i*pri[j]]=phi[i]*pri[j];
break;
}
else phi[i*pri[j]]=phi[i]*phi[pri[j]];
}
}
}
int qpow(ll a,ll b,int mod){
ll res=1;
while(b){
if(b&1) res=res*a%mod;
a=a*a%mod; b>>=1;
} return res;
}
void divide(int x){
for(int i=2;i*i<=x;i++){
if(x%i==0){
factor.push_back(i);
while(x%i==0) x/=i;
}
}
if(x>1) factor.push_back(x);
}
bool exist(int n){
if(n==2||n==4) return 1;
if(n%2==0) n/=2;
for(int i=2;pri[i]<=n;i++){
if(n%pri[i]==0){
while(n%pri[i]==0) n/=pri[i];
return n==1;
}
}
return 0;
}
int main(){
init(1000000); scanf("%d",&T);
while(T--){
int n,d; scanf("%d%d",&n,&d);
if(!exist(n)){
puts("0\n");
continue;
}
factor.clear(); ans.clear(); divide(phi[n]);
int g;
for(int i=1;;i++){
bool is=1;
if(__gcd(i,n)!=1) continue;
for(int j=0;j<factor.size();j++){
if(qpow(i,phi[n]/factor[j],n)==1){ is=0; break; }
}
if(is){ g=i; break; }
}
ll power=1;
for(int s=1;ans.size()<phi[phi[n]];s++){
power=power*g%n;
if(__gcd(phi[n],s)==1) ans.push_back(power);
}
}
}
单位根反演:
主要形式:
[k∣n]=k1i=0∑k−1ωkin
在模
m 意义下,取
ωk=gkφ(m),一般题目的
m 为质数,所以
ωk=gkm−1
多项式中的问题:
对于多项式
f(x),求
∑i[xi]f(x)[k∣i]
用单位根反演:
Ans=∑i[xi]f(x)k1∑j=0k−1ωkij=k1∑j=0k−1∑i[xi](ωkj)if(x)=k1∑j=0k−1f(ωkj)
例题:
约定:保证
k∣mod−1 且
mod 为质数且存在模
mod 的原根
求
∑i=0n(in)[k∣i]
解答:
-
Ans=k1∑i=0k−1f(ωki),其中
[xi]f(x)=(in)
-
f(x)=k1∑i(in)xi=(1+x)n
-
Ans=k1∑i=0k−1(1+ωki)n
求
∑i=0n(in)siai%4
解答:
-
枚举
j=i%4,求
∑i=0n(in)siaj[4∣i−j]
-
Ans=aj∑i=0n(in)si×41∑t=03ω4ti−tj
-
再枚举
t,
Ans=4ω4tjaj∑i=0n(in)(s×ω4t)i
-
后面的式子就是
(s×ω4t+1)n
求
∑i=1n[k∣i](in)Fi,其中
Fi 表示斐波那契数列
解答:
-
值得注意的是,矩阵乘法和单位根反演是兼容的
-
[Fi−1Fi−2]∗[1110]=[FiFi−1]
-
Fi 是矩阵的第一项,我们可以求出最终的矩阵,则答案为此矩阵的第一项
-
Ans=∑i=1n[k∣i](in)G∗Ai,其中
G 为初始矩阵,
A 为转移矩阵
-
反演可得
Ans=kG∑i=0k−1(Aωki+E)n,其中
E 为单位矩阵
求
∑i=0(ni+xk)
解答:
- Ans=n1∑i=0n−1ωn−ix(1+ωni)k
求
∑i=0n(in)pi⌊ki⌋
解答:
-
Ans=∑i=0n(in)pi∗ki−imodk
-
Ans=k1∑i=0n(in)pii−k1∑i=0n(in)pi(imodk)
-
先不管
k1,将式子拆成左右两边处理
-
left=∑i=0n(in)pii
-
left=n∑i=1n(i−1n−1)pi
-
left=np∑i=0n−1(in−1)pi
-
left=np(p+1)n−1
-
right=∑i=0n(in)pi(imodk)
-
right=∑i=0n(in)pi∑t=0k−1[t=imodk]t
-
[t=imodk]=[k∣i−t]=k1∑j=0k−1ωkj(i−t)
-
right=k1∑i=0n(in)pi∑t=0k−1t∑j=0k−1ωkjiωk−jt
-
不管
k1,
right→∑i=0n(in)piωkji∑t=0k−1t∑j=0k−1ωk−jt
-
right=(ωkjp+1)n∑t=0k−1t∑j=0k−1ωk−jt
-
枚举 j,不管定值
(ωkjp+1)n,
right→∑t=0k−1tωk−jt
-
我们知道,
∑i=1nwi=w−1wn+1−w
-
设
F(n,w)=∑i=0niwi=∑i=1niwi
-
wF(n,w)=∑i=0niwi+1=∑i=1n+1(i−1)wi
-
(w−1)F(n,w)=nwn+1−∑i=1nwi=nwn+1−w−1wn+1−w
-
right=ωk−j−11((k−1)ωk−jk−ωk−j−1(ωk−jk−ωk−j))
-
right=ωk−j−11((k−1)−ωk−j−11−ωk−j)=ωk−j−1k
-
综上,
Ans=k1(np(p+1)n−1−∑j=0k−1ωk−j−1(ωkjp+1)n),注意讨论
ωk−j=1 的情况
可转化为:
1,2,…,n 的集合,求有多少个子集,满足子集元素和为
k 的倍数,保证
k∣n
注意:此题不满足约定
解答:
-
构造生成函数
f(x)=∏i=1n(1+xi),则
[xk]f(x) 就是子集和为
k 的子集个数
-
不难得到,
Ans=∑i[xi]f(x)[k∣i]
-
Ans=k1∑i=0k−1f(ωki)
-
考虑求
f(ωki),设
d=gcd(i,k),则
f(ωki)=f(ωdkdi)
-
f(ωdkdi)=(i=0∏dk−1(1+ωdki))knd
-
我们知道
xn−1=∏i=0n−1(x−ωni),代入
x=−1,得
(−1)n−1=∏i=0n−1(−1−ωni)⇒∏i=0n−1(1+ωni)=1−(−1)n
-
f(ωdkdi)=(1−(−1)dk)knd,可见当
2∤dk 时有贡献
-
Ans=k1∑d∣k2knd∑i[(i,k)=d][2∤dk]
-
Ans=k1∑d∣k2kndφ(dk)[2∤dk]
-
设
k=u×2m,其中
2∤u,则
d=v×2m 才满足
[2∤dk]
-
最终可得
Ans=k1∑d∣u2undφ(du)
给定多项式
f(x),求
f(c0),f(c1),…,f(cm)
解答:
虽然与单位根反演无关
-
F(ci)=∑jajcij
-
人类智慧:
ij=(2i+j)−(2i)−(2j)
-
F(ci)=c−(2i)∑jajc−(2j)×c(2i+j)
-
记
Am−i=aic−(2i),
Bi=c(2i)
-
F(ci)=c−(2i)∑jAm−j×Bi+j,发现是卷积,可做
矩阵的转移是平凡的,可将问题变为对于每个
t,求
∑i=0L(iL)[i≡t(modk)]Wi
解答:
-
先定
t,
∑i=0L(iL)[i≡t(modk)]Wi=k1∑i=0k−1ωk−it(Wωki+E)L
-
构造多形式
f(x),满足
[xi]f(x)=k1(Wωki+E)L
-
Anst=∑i=0k−1ωk−it[xi]f(x)=f(ωk−t)=f((ωk1)t)
-
记
c=ωk1,即求所有的
f(ci),用上一题的做法即可
{0,1,…,n−1} 中选
k 个数,和为
n 的倍数的方案数,模
1e9+7,
k≤1e3,
n≤1e9
注意:此题不满足约定
解答:
让我们请出二元生成函数
-
Ans=∑i[n∣i][xi][yk]∏j=0n−1(1+xjy)
-
Ans=∑in1∑t=0n−1ωnti[xi][yk]∏j=0n−1(1+xjy)
-
Ans=n1∑t=0n−1[yk]∏j=0n−1(1+ωntjy)
-
设
d=gcd(t,n),
Ans=n1∑t=0n−1[yk](∏i=0dn−1(1+ωdniy))d
-
我们知道
xn−1=∏i=0n−1(x−ωni),代入
x=−y1,得
(−y1)n−1=∏i=0n−1(−y1−ωni)⇒∏i=0n−1(1+ωniy)=1−(−y)n
-
Ans=n1∑d∣nφ(dn)[yk](1−(−y)dn)d
-
Ans=n1∑d∣nφ(d)[yk](1−(−y)d)dn,可以看出,当
d∣k 时才有贡献
-
Ans=n1∑d∣n,kφ(d)[ydk](1+(−1)d+1y)dn
-
Ans=n1∑d∣n,kφ(d)(dkdn)(−1)(d+1)dk,发现
k 较小,可做
给定二维数组,问是否有排列
p,使
k∣∑i=1nai,pi 且
∀i,ai,pi=−1
数据范围:
1≤n,k≤100
解答:
-
不易想到,行列式的完全展开式里自带枚举排列
-
构造矩阵
A,当
ai,j=−1 时,
Ai,j=0,否则
Ai,j=xai,j
-
若
∃k∣i,[xi]det(A)=0,则有解
-
若都等于 0,也可能是正负抵消了,因此将
Ai,j=rand()×xai,j,这样可以避免正负抵消
-
因为加了随机化,事实上,求
Ans=∑k∣i[xi]det(A) 是否为 0 即可
-
单位根反演,
Ans=k1∑i=0k−1f(ωki),其中
f(x) 就是
det(A) 对应的多项式
-
将每个
ωki 代入算行列式即可
总结:何时用单位根反演:
出现以下情况时,可以考虑:
-
k∣mod−1,
mod 为质数,有模
mod 的原根
-
-
i≡x(modk)⇒[k∣i−x]
-
⌊ki⌋,枚举
j=imodk,变为
ki−j
-
∑if(ki+x),可化为
∑jf(j)[j≡x(modk)]
-