基础数论

gcd ⁡ , l c m \gcd,lcm gcd,lcm

简记 g c d ( x , y ) = ( x , y ) , l c m ( x , y ) = [ x , y ] gcd(x,y)=(x,y),lcm(x,y)=[x,y] gcd(x,y)=(x,y),lcm(x,y)=[x,y].
g c d , l c m gcd,lcm gcd,lcm可以看做指数取 m i n , m a x min,max min,max.

简单应用:
x 1 , x 2 . . . x n x_1,x_2...x_n x1,x2...xn g c d gcd gcd.
w = max ⁡ x i w=\max x_i w=maxxi.
则复杂度为 O ( n + log ⁡ w ) O(n+\log w) O(n+logw).(因为每次做gcd的因子都非升, w w w总共有 log ⁡ w \log w logw级别的因子数,所以得证).

欧拉定理

( a , m ) = 1 , a φ ( m ) ≡ 1 ( m o d    m ) (a,m)=1,a^{\varphi (m)}\equiv 1 (\mod m) (a,m)=1,aφ(m)1(modm)
证明:对于 m m m的简化剩余系 x 1 , x 2 . . . . x φ ( m ) x_1,x_2....x_{\varphi(m)} x1,x2....xφ(m),每个数同乘 a a a,
这时得到的集合不变 ( a , b , c ⊥ m , a ≢ b → a c ≢ b c ( m o d    m ) ) (a,b,c\bot m,a\not \equiv b\rightarrow ac\not \equiv bc(\mod m)) (a,b,cm,abacbc(modm)),所以得证.

拓展:
a b ≡ a m i n ( b , b m o d    φ ( m ) + φ ( m ) ) , d = ( a , m ) > 1 a^b\equiv a^{min(b,b\mod \varphi(m)+\varphi(m))},d=(a,m)>1 abamin(b,bmodφ(m)+φ(m)),d=(a,m)>1.
证明:对于 b ≤ φ ( m ) b\le \varphi(m) bφ(m),显然取前面部分,保持不变.

此时,对于剩下部分,我们把 a a a的质因子按和 m m m是否互质分类.

显然如果互质的质因数的话, p φ ( m ) ≡ 1 ( m o d    m ) p^\varphi(m)\equiv 1(\mod m) pφ(m)1(modm),所以删去若干 φ ( m ) \varphi(m) φ(m)的倍数无所谓.

引理:
∀ x a y b = k , a , b ≤ φ ( k ) \forall x^a y^b=k,a,b\le \varphi(k) xayb=k,a,bφ(k).
先证明 k = p c , 满 足 c ≤ φ ( k ) k=p^c,满足c\le \varphi(k) k=pc,cφ(k).
考虑证明 p = 2 p=2 p=2, c = 1 , 2 , 3 c=1,2,3 c=1,2,3显然成立,然后归纳可证.
对于 p > 2 p>2 p>2等式右边增大,由 p = 2 p=2 p=2的情况推广即可.
对于 n = p c q d , 则 需 要 满 足 m a x ( c , d ) ≤ φ ( n ) n=p^cq^d,则需要满足max(c,d)\le \varphi(n) n=pcqd,max(c,d)φ(n),这个可以由 c ≤ φ ( p c ) , d ≤ φ ( q d ) c\le\varphi(p^c),d\le \varphi(q^d) cφ(pc),dφ(qd)推得.

m = a r t ( t ⊥ a ) m=a^r t(t\bot a) m=art(ta),由欧拉定理得: a φ ( t ) ≡ 1 ( m o d    t ) a^{\varphi(t)}\equiv 1(\mod t) aφ(t)1(modt).
又因为 φ ( t ) ∣ φ ( m ) \varphi(t)|\varphi(m) φ(t)φ(m),所以 a φ ( m ) ≡ 1 ( m o d    t ) a^{\varphi(m)}\equiv 1(\mod t) aφ(m)1(modt).
两边同时乘上 a r a^r ar,则有 a φ ( m ) + r ≡ a r ( m o d    m ) a^{\varphi(m)+r}\equiv a^r(\mod m) aφ(m)+rar(modm).
由引理可知 r ≤ φ ( m ) r\le \varphi(m) rφ(m),又因为 c > φ ( m ) c>\varphi(m) c>φ(m),所以 r ≤ c , a c = a c − r + r = a c − r + φ ( m ) + r = a c + v a r p h i ( m ) ( m o d    m ) r\le c,a^c=a^{c-r+r}=a^{c-r+\varphi(m)+r}=a^{c+varphi(m)}(\mod m) rc,ac=acr+r=acr+φ(m)+r=ac+varphi(m)(modm)

综上可得:
a b = { a b m o d    φ ( m ) ( a ⊥ m ) a b ( ( a , m ) > 1 , b ≤ φ ( m ) a b m o d    φ ( m ) + φ ( m )      o t h e r w i s e a^b=\begin{cases} a^{b\mod \varphi(m)}(a\bot m) \\a^b((a,m)>1,b\le \varphi(m)\\a^{b\mod\varphi(m)+\varphi(m)}~~~~otherwise\end{cases} ab=abmodφ(m)(am)ab((a,m)>1,bφ(m)abmodφ(m)+φ(m)    otherwise

a ( mod   m ) a(\text{mod} ~~m) a(mod  m)的阶

( a , m ) = 1 (a,m)=1 (a,m)=1的情况下, a ( m o d    m ) a(\mod m) a(modm)的阶可以简记为 o r d m ( a ) ord_m(a) ordm(a),它表示的是最小的x使得 a x ≡ 1 ( m o d    m ) a^x\equiv 1(\mod m) ax1(modm).

显然 a φ ( m ) ≡ 1 ( m o d    m ) a^{\varphi(m)}\equiv 1(\mod m) aφ(m)1(modm).
有性质: o r d m ( a ) ∣ φ ( m ) ord_m(a)|\varphi(m) ordm(a)φ(m),这个可以用反证法证明(设 φ ( m ) = x t + r ( 0 < r < x ) \varphi(m)=xt+r(0<r<x) φ(m)=xt+r(0<r<x),然后可推出和最小性矛盾).
我们对 φ ( m ) \varphi(m) φ(m)质因数分解,设 φ ( m ) = ∏ p i k i \varphi(m)=\prod p_i^{k_i} φ(m)=piki.
我们记 o = x o=x o=x,初始时 o = φ ( m ) o=\varphi(m) o=φ(m).
然后我们不断尝试除质因子即可.

原根

g 1 , g 2 . . . g φ ( m ) g^1,g^2...g^{\varphi(m)} g1,g2...gφ(m) m o d    m \mod m modm下互不相等,那么我们称 g g g为模 m m m的原根.

性质:

  1. 有原根的 m = 1 , 2 , 4 , p a , 2 p a m=1,2,4,p^a,2p^a m=1,2,4,pa,2pa( p p p为奇素数).
  2. m m m φ ( φ ( m ) ) \varphi(\varphi(m)) φ(φ(m))个原根.
    这个涉及群的一些奇怪的东西,目前还不会证明.
    就证明一下比较简单的: p 有 φ ( p − 1 ) p有\varphi(p-1) pφ(p1)个原根吧:
    先假设有一个原根 g g g,那么 g i ( i ⊥ p − 1 ) g^i(i\bot p-1) gi(ip1)也为原根.
    证明显然,因为如果有 gcd ⁡ ( i , p − 1 ) > 1 \gcd(i,p-1)>1 gcd(i,p1)>1,那么在小于 φ ( p ) \varphi(p) φ(p)次内就会在 = 1 =1 =1,与定义矛盾.
    所以原根总共有 φ ( p − 1 ) \varphi(p-1) φ(p1)个.

原根的求法.(一般来说是对于奇素数 p p p而言求原根,然后使得一些运算转化为四则运算)

for i: [2,p)
	for j in prime(p-1).
		if i^((p-1)/j) = 1,不是原根.

当然由于原根较多可以采取随机的方法.

还有一种奇技淫巧是用 N T T NTT NTT卷积和暴力卷积进行对拍,拍上了就是原根.

裴蜀定理

( a , b ) = d , 则 存 在 a x + b y = d (a,b)=d,则存在ax+by=d (a,b)=d,ax+by=d.
必要性比较显然,充分性可以利用欧几里得算法进行归纳证明.

卢卡斯定理:

( n m ) ≡ ( n % p n % p ) ( ⌊ n p ⌋ ⌊ m p ⌋ ) ( m o d    p ) ) \boxed{\dbinom n m\equiv \dbinom{n\%p}{n\%p} \dbinom{\lfloor \dfrac n p\rfloor }{\lfloor \dfrac m p\rfloor }(\mod p))} (mn)(n%pn%p)(pmpn)(modp))

证明:二项式定理+费马小定理.

{ 1 + x p ≡ 1 + x ( 1 + x ) p ≡ 1 + x → ( 1 + x ) p ≡ 1 + x p ( m o d    p ) → ( 1 + x ) n ≡ ( 1 + x ) ⌊ n p ⌋ p ( 1 + x p ) n % p ≡ ( 1 + x p ) ⌊ n p ⌋ ( 1 + x n % p ) ( m o d    p ) \begin{cases} 1+x^p\equiv 1+x\\(1+x)^p \equiv 1+x\end{cases} \rightarrow (1+x)^p \equiv 1+x^p(\mod p)\rightarrow (1+x)^n\equiv(1+x)^{\lfloor \dfrac n p \rfloor p}(1 +x^p)^{n\%p}\equiv (1+x^p)^{\lfloor \dfrac n p \rfloor }(1+x^{n\%p})(\mod p) {1+xp1+x(1+x)p1+x(1+x)p1+xp(modp)(1+x)n(1+x)pnp(1+xp)n%p(1+xp)pn(1+xn%p)(modp).(费马小定理)

然后我们带入二项式定理,考究系数的关系.

为了方便,以后的下去整忽略不写.

∑ i = 0 n C n i x i ≡ ∑ i = 0 n / p C n / p i C n i x i p ∗ ∑ j = 0 n % p C n % p j x j ( m o d    p ) \sum_{i=0}^n C_n^i x^i\equiv \sum_{i=0}^{ n/p} C_{n/p}^i C_n^i x^{ip} *\sum_{j=0}^{n\% p} C_{n\% p}^j x^j(\mod p) i=0nCnixii=0n/pCn/piCnixipj=0n%pCn%pjxj(modp)

∀ i ∈ [ 0 , n ] ∩ N , i = s p + t ( p , t ∈ N ) , C n i x i ≡ C n / p s x s p C n % p t x t \forall i\in [0,n]\cap \N,i=sp+t(p,t\in \N),C_n^ix^i\equiv C_{n/p}^s x^{sp}C_{n\%p}^tx^t i[0,n]N,i=sp+t(p,tN),CnixiCn/psxspCn%ptxt

消去 x x x,则可得到卢卡斯定理.

实现:递归处理.复杂度: O ( log ⁡ p n ) O(\log_p n) O(logpn).(不计预处理阶乘的时间)

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
const int N=1e5+10;
ll jc[N],jc_inv[N],ans;
ll power_mod(ll a,ll b,ll c)
{
	ll ans=1%c;a%=c;
	while(b>0)
	{
		if(b&1)ans=ans*a%c;
		a=a*a%c;b=b>>1;
	}
	return ans;
}
int t,p,n,m;
void dfs(int a,int b)
{
	if(!b)return;
	dfs(a/p,b/p);
	ans=ans*(jc[a%p]*jc_inv[a%p-b%p]*jc_inv[b%p]%p)%p;
}
int main()
{
	scanf("%d",&t);
	jc[0]=jc_inv[0]=1;
	while(t--)
	{
		scanf("%d%d%d",&n,&m,&p);
		ans=1;
		for(int i=1;i<=p;i++)
		{
			jc[i]=jc[i-1]*i%p;
			jc_inv[i]=power_mod(jc[i],p-2,p);
		}
		dfs(n+m,m);
		printf("%lld\n",ans);
	}
	return 0;
}

拓展卢卡斯:

已知 n , m , p n,m,p n,m,p,求 ( n m ) m o d    p \boxed{\dbinom n m \mod p} (mn)modp(其中 p p p不为质数)

推导:设 p = ∏ p i k i p=\prod p_i^{k_i} p=piki,则我们只要求解所有 ( n m ) m o d    p i k i \dbinom n m \mod p_i^{k_i} (mn)modpiki,最后用中国剩余定理合并即可.

此时我们就求 n ! m ! ( n − m ) ! m o d    p k \dfrac {n!}{m!(n-m)!}\mod p^k m!(nm)!n!modpk(为了方便这里的p是质数,与上面的意义不同).

由于不一定有逆元,所以我们可以先把 p p p的倍数约去,即 n ! p x m ! p y ( n − m ) ! p z ∗ p x − y − z m o d    p k \dfrac {\dfrac {n!}{p^x}}{\dfrac{m!}{p^y} \dfrac {(n-m)!} {p^z} }*p^{x-y-z}\mod p^k pym!pz(nm)!pxn!pxyzmodpk.

定义 F ( x ) F(x) F(x)表示 x ! x! x!除去 p p p的因子后 m o d    p k \mod p^k modpk的结果.则有:

F ( x ) = p n / p F ( n / p ) ∏ i = 1 n / p k ∗ p k i ( i m o d    p ≠ 0 ) ∏ i = n / p k ∗ p k + 1 n i ( i m o d    p ≠ 0 ) F(x)=p^{n/p}F(n/p) \prod_{i=1}^{n/p^k*p^k} i(i\mod p\ne 0)\prod_{i=n/p^k*p^k+1}^n i(i\mod p\ne 0) F(x)=pn/pF(n/p)i=1n/pkpki(imodp=0)i=n/pkpk+1ni(imodp=0).

PS:前面部分表示含 p p p的因子的情况.

中间部分有周期性,我们可以减小枚举范围.

而且 p p p要消去,所以可以忽略.

所以 F ( x ) = F ( n / p ) ∗ ( ∏ i = 1 p k i ( i m o d    p ≠ 0 ) ) n / p k ∗ ∏ i = 1 n − n / p k ∗ p k i ( i m o d    p ≠ 0 ) F(x)=F(n/p)*(\prod_{i=1}^{p^k} i(i\mod p\ne 0))^{n/p^k}*\prod_{i=1}^{n-n/p^k*p^k} i(i\mod p\ne 0) F(x)=F(n/p)(i=1pki(imodp=0))n/pki=1nn/pkpki(imodp=0)

递归处理即可.递归层数 log ⁡ p n \log_p n logpn,单层扫描 p k p^k pk.

总复杂度: O ( log ⁡ p n p k ) O(\log_p^n p^k) O(logpnpk).

之后我们定义 G ( x ) G(x) G(x)表示 x x x中含有多少个 p p p个因子,复杂度: O ( log ⁡ p n ) O(\log_p n) O(logpn).

单次求解 C n m m o d    p i k i C_n^m \mod p_i^{k_i} Cnmmodpiki的复杂度: O ( p k log ⁡ p n ) O(p^k \log_p^n) O(pklogpn).

合并复杂度: O ( log ⁡ p k T ) , T O(\log p^k T),T O(logpkT),T为质因子个数.

总复杂度可以认为是: O ( p log ⁡ p ) O(p\log p) O(plogp).

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=66;
typedef long long ll;

ll power(ll a,ll b,ll mod) {
	ll c=1;
	while(b&&c) {
		if(b&1) c=c*a%mod;
		b /= 2; a=a*a%mod;
	}
	return c;
}

void exgcd(ll a,ll b,ll &x,ll &y) {
	if(!a) {x=0; y=1; return ;}
	exgcd(b%a,a,y,x); x-=b/a*y;
}

ll inv(ll a,ll p) {
	ll x,y; exgcd(a,p,x,y);
	return (x%p+p)%p;
}

ll F(ll n,ll p,ll pk) {
	if(!n) return 1;
	ll s=1;
	for(int i=1;i<pk;i++)
		if(i%p) s=s*i%pk;
	s=power(s,n/pk,pk);
	for(int i=n%pk; i;i--)
		if(i%p) s=s*i%pk;
	return F(n/p,p,pk)*s%pk;
}

ll G(ll n,ll p) {
	ll s=0;
	while(n) s+=(n/=p);
	return s;
}

ll C(ll n,ll m,ll p,ll pk) {
	ll a=F(n,p,pk),b=inv(F(m,p,pk),pk),c=inv(F(n-m,p,pk),pk),d=power(p,G(n,p)-G(m,p)-G(n-m,p),pk);
	return a*b%pk*c%pk*d%pk;
}

ll A[N],B[N];
ll lucas(ll n,ll m,ll p) {
	int cnt=0;ll x=p;
	for(int i=2;i*i<=x;i++) if(x%i==0) {
		ll y=1;
		while(x%i==0) y*=i,x/=i;
		A[++cnt]=y; B[cnt]=C(n,m,i,y);
	}
	if(x>1) A[++cnt]=x,B[cnt]=C(n,m,x,x);
	ll ans=0;
	for(int i=1;i<=cnt;i++) 
		(ans += B[i]*(p/A[i])%p*inv(p/A[i],A[i])%p) %= p;
	return ans;
}

int main() {
	ll n,m,p; scanf("%lld%lld%lld",&n,&m,&p);
	printf("%lld\n",lucas(n,m,p)); return 0;
}

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值