qbxt五一数学Day2

1. 判断素数(素性测试)

1. O(n) 试除

bool isprime(int n)
{
	if (n<2) return false;
	for (int i=2;i*i<=n;i++)
		if (!(n%i)) return false;
	return true;
}

2. Miller-Rabin 素性测试

Theorm 1

n 是素数,则对于任意 1an,设 n1=d2r,则

ad1(modn),0irad2i1(modn)

中至少有一个成立 .

随便找若干个数 a 进行判定,很大概率对(4~8 个在 long long 范围稳了)(取质数效果较好)

时间复杂度 O(klog2n)

const int PrimeList[]={2,3,5,11,37,43,67,73,97}; // for Miller-Rabin
ll qmul(ll a,ll n,ll P)
{
	ll ans=0; if (!n) return 0;
	while (n)
	{
		if (n&1) ans=(ans+a)%P;
    	n>>=1; a=(a+a)%P;
	} return ans%P;
}
ll qpow(ll a,ll n,ll P)
{
	ll ans=1;
	while (n)
	{
		if (n&1) ans=qmul(ans,a,P)%P;
		n>>=1; a=qmul(a,a,P)%P;
	} return ans;
}
bool miller_rabin(ll n,int a)
{
	ll d=n-1,r=0;
	while (!(d&1)){++r; d>>=1;}
	ll x=qpow(a,d,n);
	if (x==1) return true;
	for (int i=0;i<r;i++)
	{
		if (x==n-1) return true;
		x=qmul(x,x,n)%n;
	} return false;
}
bool MillerRabin(ll n)
{
	if (n<2) return false;
	for (int i=0;i<9;i++)
	{
		if (n==PrimeList[i]) return true;
		if (n%PrimeList[i]==0) return false;
		if (!miller_rabin(n,PrimeList[i])) return false;
	} return true;
}

* 欧拉函数

定义:

φ(n) 定义为 1n 中与 n 互质的数的个数,即:

φ(n)=i=1n[gcd(i,n)=1]

Theorm *

欧拉函数的求值公式:

φ(n)=n(11p1)(11p2)(11pr)wheren=i=1rpiαi

Proof:容斥原理

公式求 φ 值:

ll phi(ll n) // O(sqrt(n))
{
	ll ans=n;
	for (int i=2;i*i<=n;i++)
		if (!(n%i))
		{
			ans=ans/i*(i-1);
			while (!(n%i)) n/=i;
		}
	if (n>1) ans=ans/n*(n-1);
	return ans;
}

Theorm *(欧拉函数是积性函数)

n,m 互质,则 φ(n)φ(m)=φ(nm) .

Proof:由求值式子显然得证 .

2. 逆元

定义:

b 使得 ab1(modm),则 b 成为 am 意义下的逆元,记作 b=a1 .

Theorm 2
逆元存在的充要条件是 gcd(a,m)=1 .

我们知道费马小定理和欧拉定理:

Theorm 3(费马小定理)

对于 gcd(a,p)=1p 为质数,有:

ap11(modp)

Theorm 4(欧拉定理)

对于 gcd(a,p)=1,有:

aφ(p)1(modp)

其中 φ 是欧拉函数 .

素数求逆元:用费马小定理,答案是 a1=ap2 .

其他:

  1. 用欧拉定理,答案是 a1=aφ(p)1 .
  2. 用 exgcd,问题等价于求解 ax+by=p .

1n 的逆元:

预处理阶乘,阶乘逆元可以

(n1)!1=n!1n

求,n 的逆元可以

n1=n!1(n1)!

求 .

3. exgcd(扩展欧几里得)

求解不定方程

ax+by=c

其中 x,y 是整数 .

Theorm 5(裴蜀定理 / 贝祖定理)

ax+by=c

有解当且仅当 gcd(a,b)c .

所以只需要处理 ax+by=gcd(a,b) 的解即可 .

注意到 gcd(a,b)=gcd(b,amodb),设 G=gcd(a,b) .

我们按照欧几里德算法(即辗转相除法),当 b=0 时,容易发现 x=1,y=0 .

若不然,如果我们知道

bx0+(amodb)y0=G

的解,我们就可以依照如下方法求 ax+by=G 的解:

bx0+(amodb)y0=bx0+(abab)y0=ay0+b(x0y0ab)

int ex_gcd(int a,int b,int& x,int& y)
{
	if (!b){x=1; y=0; return a;}
	int xp,yp,g=ex_gcd(b,a%b,xp,yp);
	x=yp; y=xp-yp*(a/b); return g;
	return 0;
}

4. 离散对数(BSGS 算法求解)

BSGS:大步小步算法北上广深·百事公司·阿姆斯特朗算法

求解同余方程

axb(modp)

其中 p 是质数 .

由费马小定理,这个 x 不会超过 p1 .

分成如下数表:

如图,将所有行转换到第一行,用一个 sethash 维护即可 .

ll BSGS(ll a,ll b,ll p) // a^x=b (mod p)
{
	int s=sqrt(p),x=1; set<int> se;
	for (int i=0;i<s;i++){se.insert(x); x=1ll*x*a%p;}
	int y=qpow(qpow(a,s,p),p-2,p),z=b;
	for (int i=1;;i++)
	{
		if (se.count(z))
		{
			z=qpow(a,(i-1)*s,p);
			for (int j=(i-1)*s;;j++)
				if (z==b) return j;
				else z=1ll*z*a%p;
		} z=1ll*z*y%p;
	}
} // 要判无解只需要判断循环次数是否过多即可 .

5. CRT(中国剩余定理)

考虑合并两个方程,

{xb1(modp1)xb2(modp2)

法一:大数翻倍法(zhx 的神仙解法)

枚举 b1,b1+p1,b1+2p1, 判断是否成立

static pair<ll,ll> MergeEqu(ll a1,ll m1,ll a2,ll m2)
{
	if (m2>m1) swap(m1,m2),swap(a1,a2);
	while (a1%m2!=a2) a1+=m1;
	return make_pair(a1,lcm(m1,m2));
}

法二:用扩展欧几里得解

x=k1p1+b1=k2p2+b2,则

k1p1k2p2=b2b1

则:

k1p1gcd(p1,p2)b2b1gcd(p1,p2)(modp2gcd(p1,p2))

用扩欧解出 k1 即可 .

6. 线性筛(xxs)

1. 筛素数

碍事筛埃氏筛:

notprime[1]=true;
for (int i=2;i<=n;i++)
{
	if (notprime[i]) continue;
	for (int j=i+i;j<=n;j++) notprime[j]=true;
}

这是对于每个素数 i 枚举它的所有倍数筛掉

我们反过来,用每个数 i 枚举它的所有素数倍:

vector<int> plist; notprime[1]=true;
for (int i=2;i<=n;i++)
{
	if (!notprime[i]) plist.push_back(i);
	for (auto x:plist)
	{
		int now=i*x;
		if (now>n) break;
		notprime[x]=true;
	}
} // C++11

/* 数组写法  */

notprime[1]=true;
for (int i=2;i<=n;i++)
{
	if (!notprime[i]) plist[++pcnt]=i;
	for (int j=1;j<=pcnt;j++)
	{
		int now=i*plist[j];
		if (now>n) break;
		notprime[plist[j]]=true;
	}
}

注意到每个数可能被筛多次,例如:

12=2×6=3×4

翻过来后就是枚举到 4,6 时,找到 2,3 筛掉 12 .

我们希望每个数只被它的最小质因子筛掉 .

我们进行模拟:

当我们发现 4 时,枚举:

  • 素数 2:筛掉 8 .
  • 素数 3:注意到 2(上一个素数)是 4 的倍数,所以后面的素数都不用枚举了,因为不是最小素因子(此处最小素因子至多是 2

用这种想法写出最终代码:

vector<int> plist; notprime[1]=true;
for (int i=2;i<=n;i++)
{
	if (!notprime[i]) plist.push_back(i);
	for (auto x:plist)
	{
		int now=i*x;
		if (now>n) break;
		notprime[x]=true;
		if (!(i%x)) break;
	}
}

2. 筛积性函数(φμ

k 是素数时:

φ(k)=k1,μ(k)=1

当第 10 行成立,显然 μ(now)=0 .

因为没有其他增加的素因子,由欧拉函数计算式得 φ(now)=xφ(x) .

如果互素(即第 11 行成立),由积性显然有 φ(now)=φ(x)φ(i)μ(now)=μ(x)μ(i)

在板子上改一改就行辣

notprime[1]=true; phi[1]=mu[1]=1;
for (int i=2;i<=n;i++)
{
	if (!notprime[i]){plist.push_back(i); phi[i]=i-1; mu[i]=-1;}
	for (auto x:plist)
	{
		int now=i*x;
		if (now>n) break;
		notprime[now]=true;
		if (!(i%x)){phi[now]=phi[i]*x; mu[now]=0; break;}
		else{phi[now]=phi[i]*phi[x]; mu[now]=mu[i]*mu[x];}
	}
}

7. 数论函数与狄利克雷卷积

1. μ

1. 定义与性质

μ:莫比乌斯函数 ,数论容斥函数 .

定义:

对于整数 n,定义:

μ(n)={1n=1(1)ri[1,r]Z:αi=10otherwise.wheren=i=1rpiαi

Theorm:对于 nm,有 μ(nm)=μ(n)μ(m)μ 是积性函数 .

Proof:

n=i=1rpiαi,m=i=1tqiβi

其中 i[1,r]Z,j[1,t]Z:piqj(即 n,m 互质).

αi=βj=1 时(其余情况易证),

μ(nm)=μ(i=1rpiαii=1tqiβi)=(1)r+t=(1)r(1)t=μ(n)μ(m)

2. 例题

问在 1n 中有多少个数可以表示为

t=xy

其中 x1,y2 .
数据范围:n1018

对于对于一个 y,存在 nyx 满足条件(显然有 ylog2(1018),即 y64).

注意到有数会重复,e.g.

64=82=43=26

答案即为:

i=264μ(i)(ni1)+1

(这个 1 +1 是为了去掉 1=1?
暴力求即可 .

2. 狄利克雷卷积

1. 定义

数论卷积(或狄利克雷(Dirichlet)卷积):

对于数论函数 f,g,定义他们的狄利克雷卷积为:

(fg)(n)=dnf(d)g(nd)

注:dn 是枚举因子 .

有性质:

  • 交换律:fg=gf .
  • 结合律:(fg)h=f(gh)
  • 分配律:(f+g)h=fh+gh

2. 特殊函数的狄利克雷卷积

μI=ε

其中 I(n)=1,ε(n)=[n=1] .

即对于 n>1,有:

dnμ(d)=0

φI=id

其中 id(n)=n .

即:

dnφ(d)=n

μid=φ

Proof:

μid=μφI=μIφ=εφ=φ

3. 例题

求和变形技巧:

  1. 增加枚举变量
  2. 交换枚举顺序
  3. 删除无用变量

Problem 1

给定 n,m,求:

i=1nj=1mgcd(i,j)

i=1nj=1mgcd(i,j)=i=1nj=1mid(gcd(i,j))=i=1nj=1mdgcd(i,j)φ(d)(增加枚举变量)=d=1ni=1ndi=1mdφ(d)(交换枚举顺序)=d=1nndmdφ(d)(删除无用变量)

(第三个等号是把 gcd 转换成枚举倍数).

然后预处理 φ,时间复杂度 O(n) .

Problem 2

给定 n,问存在多少 1i,jn,使得 i,j 互质 .

显然题目让求的是:

i=1nj=1nε(gcd(i,j))=i=1nj=1mdgcd(i,j)μ(d)(增加枚举变量)=d=1ni=1ndi=1mdμ(d)(交换枚举顺序)=d=1nndmdμ(d)(删除无用变量)

和上一题几乎一样 [表情]

3. 莫比乌斯反演

g(n)=dnf(d)f(x)=dnμ(d)g(nd)

g=fIf=μg

Proof:

g=fIμg=fIμμg=fεμg=f

8. 计数

1. 计数原理

1. 加法原理

一件事若干类(并列),方案数加起来

2. 乘法原理

一件事若干步(递进),方案数乘起来

2. 排列组合

定义

组合:n 中无序选 r

C(n,r)=(nr)=n!r!(nr)!

排列:n 中有序选 r

P(n,r)=A(n,r)=nr_=n!(nr)!

性质

(n+mn)=(n+mm)

组合意义:选不选的

(nm)=(n1m1)+(n1m)

组合意义:第一件选不选

(n+r+1r)=(n+rr)+(n+r1r1)++(n0)=i=0r(nriri)

反复用前面那个式子

(nl)(lr)=(nr)(nrlr)

组合意义:选两次

(n0)+(n1)++(nn)=2n

组合意义:取数用乘法原理、组合数两种算法

(n0)(n1)+(n2)=0

组合意义:建立奇数项与偶数项的一一对应,以达成消去的效果(第一项取反) .

(rr)+(r+1r)++(nr)=(n+1r+1)

qwq

(1+x)n=k=0n(nk)xnk=k=0n(nk)xk

(二项式定理)

组合意义:多项式乘法选数 .

几道小题

Problem 1

n 里选 k 数,数字可以相同,求方案数.

一个独特的解法:设选 a1a2ak .
构造 g1=a1,g2=a2+1,g3=a3+2,,然后对 g 作组合,得答案为

(n+k1k)

Problem 2

n 里选 k 数,数字不能相邻,求方案数.

类似的设选 a1<a2<<ak .
构造 g1=a1,g2=a21,g3=a32,,然后对 g 作组合,得答案为

(nk+1k)

Problem 3

计算

k=1n(nk)2

k=1n(nk)2=k(nk)(nnk)=(2nn)

第二个等号用组合意义:

posted @   yspm  阅读(117)  评论(1编辑  收藏  举报
编辑推荐:
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
😅​
点击右上角即可分享
微信分享提示