数学

等比数列求和公式

\[a_1(1-q^n)\over 1-q \]

自然数幂和

\[\sum_{i=1}^ni^k \]

可以使用拉格朗日插值求,复杂度 \(O(k)\)

这里给出 \(k\leq 3\) 的公式:

\[\sum_{i=1}^ni={n(n+1)\over 2} \sum_{i=1}^ni^2={n(n+1)(2n+1)\over 6} \sum_{i=1}^ni^3={n^2(n+1)^2\over 4} \]

拉格朗日插值求法:

以下是求 \(\sum_{i=1}^ni^k\)

int langrange(int n,int k){
	n%=mod;
	for(int i=1;i<=k+2;i++) y[i]=(y[i-1]+qpow(i,k))%mod;
	int res=0;
	pre[0]=1;suf[k+3]=1;
	for(int i=1;i<=k+2;i++) pre[i]=pre[i-1]*(n-i+mod)%mod;
	for(int i=k+2;i>=1;i--) suf[i]=suf[i+1]*(n-i+mod)%mod;
	for(int i=1;i<=k+2;i++){
		res=(res+((k+2-i)&1? -1: 1)*y[i]*inv[i-1]%mod*inv[k+2-i]%mod*pre[i-1]%mod*suf[i+1]%mod+mod)%mod;
	}
	return res;
}

裴蜀定理

\(\gcd(a,b)=d\),则对于任意 \(x, y\)\(ax+by\)\(d\) 的倍数。

\(\gcd(a,b)=d\),则关于 \(x, y\) 的方程 \(ax+by=d\) 一定存在整数解。

Lucas定理

\[\binom{n}{m}=\binom{\lfloor {n\over p}\rfloor}{\lfloor{m\over p}\rfloor}\binom{n\mod p}{m\mod p}\mod p \]

\(p\) 是质数

不能直接通过 fac[n]*inv[m]*inv[n-m] 求出,因为在 \(x\geq p\) 时,fac[x] \(=0\)

同样需要注意在预处理 fac[]inv[] 时,循环上界必须为 \(p-1\),否则预处理的 inv[] 数组会全为 \(0\)

扩展欧几里得算法

求解 \(ax+by=\gcd(a,b)\) 的一组解

void exgcd(long long a,long long b,long long &x,long long &y){
	if(b==0){
		x=1;y=0;//此时a是gcd
		return;
	}
	exgcd(b,a%b,y,x);
	y-=a/b*x;
}

欧拉定理与费马小定理的对照

欧拉定理:\(a^{\varphi(p)}=1\bmod p,\gcd(a,p)=1\)

费马小定理:\(a^{p-1}=1\bmod p,p为质数\)

可以说费马小定理是欧拉定理的一种特殊形式

扩展欧拉定理

\(a^b\bmod\) \(p=\)

\[\left\{ \begin{matrix} a^{b \bmod \varphi(p)},\gcd(a,p)=1\\ a^b,\gcd(a,p)\neq1,b<\varphi(p)\\ a^{b \bmod \varphi(p) + \varphi(p)}, \gcd(a,p)\neq1,b\geq\varphi(p) \end{matrix} \right. \]

核心操作如下

for(int i=1;i<=len;i++){
	x=x*10+(c[i]-'0');
	x%=p;
}
x+=p;
cout<<qpow(a,x,mod);

质数筛

void prime(){
	for(int i=2;i<=n;i++){
		if(!in[i]) pr[++cnt]=i;
		for(int j=1;j<=cnt&&pr[j]*i<=n;j++){
			in[pr[j]*i]=1;
			if(i%pr[j]==0) break;
		}
	}
}

欧拉函数

基本性质:

  1. 积性函数:\(\varphi(a\times b)=\varphi(a)\times \varphi(b),\) \(\gcd(a,b)=1 \\\)
  2. \(\varphi(p^k)=p^{k-1}\times (p-1)=p^k-p^{k-1} \\\)
  3. 有时根据需要,要表示成 \(\varphi(x)=\Pi_i k_i^{p_i}\) (所有 \(k_i\) 互质)

\(O(\sqrt n)\) 求单个数的 \(\varphi\)

原理:\(\varphi(p^k)=p^k-p^{k-1}=p^k\times(1-{1\over p})\),而 \(1-{1\over p}={p-1 \over p}\)

int Phi(long long x){
	long long ans=x;
	for(int i=2;i*i<=x;i++){//其实就是分解质因数的过程
		if(x%i==0){
			ans=ans*(i-1)/i;
			while(x%i==0) x/=i;
		}
	}
	if(x>1) ans=ans*(x-1)/x;//可能最后x也是个待分解的质数
	return ans;
}

线性筛欧拉函数

void Phi(){
	ph[1]=1;
	for(int i=2;i<=n;i++){
		if(!in[i]){
			ph[i]=i-1;
			a.push_back(i);
		}
		for(int j=0;j<a.size();j++){
			if(a[j]*i>n) break;
			in[a[j]*i]=1;
			if(i%a[j]==0){
				ph[i*a[j]]=ph[i]*(a[j]);
				break;
			}
			else ph[a[j]*i]=ph[a[j]]*ph[i];
		}
	}
}

莫比乌斯函数

\(\mu(n)\)=

\[\left\{ \begin{matrix} 1,n=0\\ 0,存在质数 x 使得 x^2|n \\ (-1)^w,otherwise(w 为 n 的质因子个数) \end{matrix} \right. \]

线性筛 \(\mu(n)\)

void Mu(){
	mu[1]=1;
	for(int i=2;i<=n;i++){
		if(!in[i]){
			pr.push_back(i);mu[i]=-1;
		}
		for(auto x:pr){
			if(x*i>n) break;in[x*i]=1;
			if(i%x==0){
				mu[i*x]=0;break;
			}
			else mu[i*x]=mu[i]*mu[x];
		}
	}
}

高斯消元

for(int i=1;i<=n;i++){
  double mx=0;
  int to;
  for(int j=i;j<=n;j++){
    if(abs(a[j][i])>mx){
      mx=abs(a[j][i]);
      to=j;
    }
  }
  if(mx<eps) continue;
  swap(a[i],a[to]);
  for(int j=1;j<=n;j++){
    if(j==i) continue;
    double p=a[j][i]/a[i][i];
    for(int k=1;k<=n+1;k++){
      a[j][k]-=p*a[i][k];
    }
  }
}
for(int i=1;i<=n;i++){
  if(abs(a[i][i])<eps){
    cout<<"No Solution";
    return 0;
  }
}
for(int i=1;i<=n;i++){
  printf("%.2lf\n",a[i][n+1]/a[i][i]);
}

中国剩余定理

求解形如

\[\left\{ \begin{matrix} x \equiv a_1 \bmod p_1\\ x \equiv a_2 \bmod p_2\\ \dots\\ x \equiv a_n \bmod p_n\\ \end{matrix} \right. \]

方程组,其中 \(p_i\) 两两互质。

构造法:

\(M=\prod_{i=1}^np_i\),令 \(M_i={M\over p_i}\)\(t_i={1\over M_i}\bmod p_i\)

那么就可以构造出一个解:\(x=\sum_{i=1}^n a_i\times M_i t_i\)

可以发现:当 \(k \not=i\) 时,\(a_i\times M_i t_i\bmod p_k=0\),因为 \(M_i\) 中含有 \(p_k\) 这个因子。

\(k=i\) 时,\(a_k\times M_i t_i\equiv a_k\bmod p_k\),因为在 \(\bmod p_k\) 意义下,\(M_i t_i \equiv 1\)

该方程的通解为:\(x=\sum_{i=1}^n a_i\times M_i t_i+kM\)

最小解为:\(x=\sum_{i=1}^n a_i\times M_i t_i\bmod M\)

注意:不能使用费马小定理求逆元,因为 \(p_i\) 互质不等同于 \(p_i\) 都为质数。

void exgcd(long long a,long long b,long long &x,long long &y){
	if(!b){
		x=1;y=0;return;
	}
	exgcd(b,a%b,y,x);
	y-=a/b*x;
}
void solve(){
	long long ans=0;
	for(int i=1;i<=n;i++){//inv是M_i,s[n]是M
		long long inv,_;
		exgcd(s[n]/a[i],a[i],inv,_);
		inv=(inv+a[i])%a[i];
		long long res=s[n]/a[i]*b[i]%s[n]*inv%s[n];
		ans+=res;
	}
	cout<<ans%tot;
}

扩展中国剩余定理

采用逐个求解法。

设已经求解了前几个方程组,\(M\) 为前几个方程组模数的 \(\operatorname{lcm}\),通解为 \(x=r_1+kM\)

考虑下一个方程:\(x=r_2\bmod p_i\),设 \(M\prime =\operatorname{lcm}(M,p_{now})\),求解完这个方程后的答案为 \(x=r_1+tM+kM\prime\),其中 \(t\) 是我们需要求解的量。

方程为 \(r1+tM+kp_{now}=r2\),整理得 \(tM+kp_{now}=r2-r1\)

根据裴蜀定理,方程有解的条件是 \(\gcd(M,p_{now})|(r2-r1)\)

然后使用扩展欧几里得算法即可求出答案。

为了避免中间结果爆 long long,需要使用 __int128

#include<bits/stdc++.h>
using namespace std;
#define int long long
const __int128 bs=1;
const int N=1e5+5;
int lcm(int a,int b){
	return bs*a*b/__gcd(a,b);
}
int lm;
int r1;
void exgcd(int a,int b,int &x,int &y){
	if(!b){
		x=1;y=0;return;
	}
	exgcd(b,a%b,y,x);
	y-=a/b*x;
}
int a[N],b[N];//a[i]为模数,b[i]为模后的值
int n;
void exCRT(){
    lm=1;r1=0;
	for(int i=1;i<=n;i++){
		int g=__gcd(lm,a[i]);
		int x=0,y=0;
		if((b[i]-r1)%g!=0){//b[i]指文章中的r2 
			cout<<-1;return;
		}
		exgcd(lm/g,a[i]/g,x,y);
		r1=(r1+bs*(b[i]-r1)/g*x*lm)%lcm(lm,a[i]);//__int128防溢出 
		lm=lcm(lm,a[i]);
	}
	cout<<(r1+lm)%lm;
}
signed main(){
	cin>>n;
	for(int i=1;i<=n;i++) cin>>a[i]>>b[i];
	exCRT();
	return 0;
}

杜教筛

用于求数论函数前缀和

原理:设

\[S(i)=\sum_{j=1}^i f(j)\\ \]

那么

\[\sum_{i=1}^n(f * g)(i)=\sum_{i=1}^n g(i)S(\lfloor {n\over i}\rfloor) \]

进一步变形:

\[\sum_{i=1}^n g(i)S(\lfloor {n\over i}\rfloor) =g(1)S(n)+\sum_{i=2}^ng(i)S(\lfloor {n\over i}\rfloor) \]

最终式子为:

\[g(1)S(n)=\sum_{i=1}^n(f * g)(i)-\sum_{i=2}^ng(i)S(\lfloor {n\over i}\rfloor) \]

等号右端的式子可以使用整除分块处理,然后可以递归求解。

一般先预处理一部分,然后其余的记忆化处理,时间复杂度 \(O(n^{2\over 3})\)

注意:必须保证 \(\sum_{i=l}^r(f * g)(i)\) 能够 \(O(1)\) 求出,才能使用杜教筛。

posted @ 2025-05-09 11:49  born_to_sun  阅读(45)  评论(0)    收藏  举报