ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

SDSC2021 Day1

2022-07-09 21:00:54  阅读:188  来源: 互联网

标签:lfloor phi frac SDSC2021 long Day1 rfloor mod


又是一年SDSC到但是我已经成为时代的眼泪啦

但我翻翻去年的笔记,好像就Day1写得还行,剩下几天就很摸

所以就只把Day1的笔记搬过来啦~(我才不会说临时起意搬笔记的原因是又有好题图了(当然不是))


配套题单

质数筛

提供一种快速的分解质因数的方法:

在线性筛的时候可以顺道求出每个数的最小的质因数,方法如下:

void init_P(){
	long long i,j;
	for(i=2;i<=N;i++){//N 是最大筛到的数
		if(!mf[i]){//mf 记录最小质因数,同时可以用于判断该数是否被筛过
			mf[i]=i;
			p[++tot]=i;
		}
		for(j=1;j<=tot && i*p[j]<=N;j++){
			mf[p[j]*i]=p[j];//根据线性筛的性质,每个合数会被自己最小的质因子筛到
			if(i%p[j]==0) break;
		}
	}
}

在求出每个数的最小的质因子后,我们可以进行快速质因数分解。

假如我们要对 \(x\) 进行分解质因数,我们可以提取出它的最小质因数作为一个分解出的因数,并 \(x:=x/mf_x\) 继续进行分解直至 \(x<1\)。

void init_F(int x){
	int i,j,u=x,v;
	while(u>1){
		ans[++cnt]=mf[u];
        u/=mf[u];
	}
}

神奇推式子题。

\[\frac{1}{x}+\frac{1}{y}=\frac{1}{n!}\Leftrightarrow \frac{xy}{x+y}=n! \Leftrightarrow xy-(x+y)n!=0 \Leftrightarrow (n!)^2+xy-(x+y)n!=(n!)^2 \Leftrightarrow \]

\[(x-n!)(y-n!)=(n!)^2 \]

所以答案就是 \((n!)^2\) 的因子个数。

怎么算呢?考虑唯一分解 \(n!=\sum p_i^{e_i}\)

有 \((n!)^2=\sum p_i^{2e_i}\)。

然后就指数加一连乘积啦~

怎么唯一分解 \(n!\) 呢?

线性筛求 \(p_i\)。对于求 \(e_i\),有公式 \(e_i=\sum\limits_{k \ge 0,p_i^k \le n}\lfloor \frac{n}{p_i^k} \rfloor\);或者在线性筛进行质因数分解(就是一开始写的那个方法)。

代码使用线性筛分解质因数:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;

const long long mod=1e9+7;
long long n,t,p[1000010],mf[1000010],e[1000010],tot,ans;

int main(){
	long long i,j,u,v;
	cin>>n;
	for(i=2;i<=n;i++){
		if(!mf[i]){
			mf[i]=i;
			p[++tot]=i;
		}
		for(j=1;j<=tot && i*p[j]<=n;j++){
			mf[p[j]*i]=p[j];
			if(i%p[j]==0) break;
		}
	}
	for(i=2;i<=n;i++){
		for(j=i;j>1;j/=mf[j]){
			e[mf[j]]++;
		}
	}
	ans=1;
	for(i=1;i<=n;i++){
		ans*=(2*e[i]+1);
		ans%=mod;
	}
	cout<<ans<<endl;
	return 0;
} 

GCD&LCM

暴力可过。

正解见花神的题解


感性理解路径一定是 \(u\to gcd(u,v) \to v\)。根据排列组合,唯一分解 \(x=\sum p_i^{e_i}\) 后,\(x \to 1\) 的路径条数为:\(\frac{(\sum e_i)!}{\prod e_i!}\)。

我们把 \(u,v\) 除以其最大公约数 \(g\),转化为 \(dis(\frac{u}{g},1)\times dis(\frac{v}{g},1)\),即可求解。

还有就是注意由于所有数都是 \(d\) 的因子,所以质数表可以直接在 \(d\) 的因子里筛。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;

const long long mod=998244353;
long long n,t,fac[110],tot,ans;
long long p[700010];

inline long long fast(long long a,long long b){
	if(b==0) return 1%mod;
	if(b==1) return a%mod;
	long long s=fast(a,b/2)%mod;
	if(b&1) return s*s%mod*a%mod;
	return s*s%mod;
}
inline void init_fac(){
	long long i;
	fac[0]=1;
	for(i=1;i<=100;i++){
		fac[i]=fac[i-1]*i%mod;
	}
}
inline void init_pri(){
	long long d=n,i,sd=sqrt(d);
	for(i=2;i<=sd;i++){
		while(d%i==0){
			p[++tot]=i;
			d/=i;
		}
	}
	if(d>1) p[++tot]=d; 
}
inline long long gcd(long long a,long long b){
	if(b==0) return a;
	return gcd(b,a%b);
}
inline long long sol(long long u){
	if(u==1) return 1;
	long long i,cnt=0,cntt=0,on,down=1;
	for(i=1;i<=tot;i++){
		cnt=0;
		while(u%p[i]==0){
			cnt++;
			u/=p[i];
		}
		down*=fac[cnt];down%=mod;
		cntt+=cnt;
	}
	on=fac[cntt];
	return on*fast(down,mod-2)%mod;
}

int main(){
	long long i,j,u,v;
	cin>>n>>t;
	init_fac();
	init_pri();
	while(t--){
		scanf("%lld %lld",&u,&v);
		if(u==v){
			cout<<1<<endl;
			continue;
		}
		j=gcd(u,v);
		printf("%lld\n",sol(u/j)*sol(v/j)%mod);
	}
	return 0;
}

进制转换

扩展欧几里得

裴蜀定理

不定方程 \(ax+by=m\) 有整数解的充要条件是 \(\gcd(a,b) \mid m\)

引理1(其实就是余数的定义):\(a \mod b=a- \lfloor \frac{a}{b} \rfloor \times b\)

设 \(d=\gcd(a,b)\),exgcd 可给出不定方程 \(ax+by=d\) 的一组特解 \((x_0,y_0)\)。

记 \(ax_1+by_1=d\)

设 \(a'=b,b'=a \mod b\),则有 \(a'x_2+b'y_2=d\)

所以 \(ax_q+by_1=a'x_2+b'y_2\)

根据引理,有 \(ax_1+by_1=bx_2+(a- \lfloor \frac{a}{b} \rfloor \times b)y_2\)

整理得 \(ax_1+by_1=ay_2+b(x_2- \lfloor \frac{a}{b} \rfloor y_2)\)

因为恒等,所以 \(x_1=y_2,y_1=x_2-\lfloor \frac{a}{b} \rfloor y_2\)

故,可以代入 \(x_2,y_2\) 递归求解直至 \(y_2=0\) 返回 \(x=1,y=0\) 回溯回去。

int exgcd(int a,int b,int &x,int &y){
	if(b==0){
		x=1;y=0;
		return a;
	}
	int t,ans;
	ans=exgcd(b,a%b,x,y);
	t=x; x=y;
	y=t-(a/b)*y;
	return ans;
}

欧拉函数

定义:\(\phi(x)=[1,x]\) 中与 \(x\) 互质的数的个数。

性质:设 \(x=\prod p_i^{e_i}\),则 \(\phi(x)=x \prod \frac{p_i-1}{p_i}\)

欧拉定理

若 \(\gcd(a,m)=1\),则 \(a^{\phi(m)} \equiv 1 \pmod m\)

考虑一个人 \((x,y)\) 可以被看到,当且仅当 \(\gcd(x,y)=1\)。所以答案就是 \((2\sum\limits_{i=1}^{n} \sum\limits_{j=1}^{i}[\gcd (i,j)=1])+1=2\sum\limits_{i=1}^{n}\phi(i)+1\)(最后加个 1 的原因是对角线可以看到一个)。

然后欧拉函数可以线性推,不过这题没必要,一般的根号筛法即可。

扩展欧拉定理

\(\forall b \ge \phi(m),a^b \equiv a^{b \mod \phi(m)+\phi(m)} \pmod m\)

根据扩展欧拉定理,\(2^{2^{2^{\cdots}}} \mod p=2^{2^{2^{2^{\cdots}}} \mod \phi(p)+ \phi(p)}\)

然后这个东西显然可以递归做。

本题需要用线性筛欧拉函数,方法见下:

在线性筛中,每一个合数都会被自己的最小质因子筛掉。记合数 \(n\) 的最小质因子是 \(p_1\),记 \(n'=\frac{n}{p_1}\)。

  1. 如果 \(p_1 \mid n'\),则 \(n'\) 包含 \(n\) 的所有质因子,那么 \(n'\) 含有 \(n\) 的所有质因子,于是有:\(\phi(n)=n \prod\limits_{i=1}^{s}\frac{p_i-1}{p_i}=p_1\times n'\prod\limits_{i=1}^{s}\frac{p_i-1}{p_i}=p_1 \times \phi(n')\)。

  2. 如果 \(p_1\nmid n'\),则 \(p_1 \bot n'\),由于 \(\phi(x)\) 是积性函数,所以 \(\phi(n)=\phi(p_1)\times \phi(n')=(p_1-1)\times \phi(n')\)

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;

long long t,P,p[10000010],tot,phi[10000010];
bool mf[10000010];

void init_phi(){
	long long i,j;
	phi[1]=1;
	for(i=2;i<=10000000;i++){
		if(!mf[i]){
			p[++tot]=i;
			phi[i]=i-1;
		}
		for(j=1;j<=tot && i*p[j]<=10000000;j++){
			mf[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);
			}
		}
	}
}
long long fast(long long a,long long b,long long mod){
	if(b==0) return 1%mod;
	if(b==1) return a%mod;
	long long s=fast(a,b/2,mod)%mod;
	if(b&1) return s*s%mod*a%mod;
	return s*s%mod;
}
long long solve(long long x){
	if(x==1) return 0;
	return fast(2,solve(phi[x])+phi[x],x)%x;
}

int main(){
	long long i,j,u,v;
	init_phi();
	cin>>t;
	while(t--){
		cin>>P;
		cout<<solve(P)%P<<endl;
	}
	return 0;
}

中国剩余定理

设有同余方程组 \(\begin{cases}x \equiv a_1(\mod m_1)\\x \equiv a_2(\mod m_2)\\ \vdots \\x \equiv a_n(\mod m_n)\end{cases}\)

其中 \(m_i\) 两两互质,求最小正整数 \(x\)。


设 \(M= \prod m_i, M_i=\frac{M}{m_i}\)

可以发现,\(m_i \mid M_j = 0\),当且仅当 \(i \ne j\)。

设 \(t_i \equiv M_i^{-1}(\mod m_i)\),则 \(a_it_iM_i \equiv \begin{cases}a_i ,\mod m_i\\0, \space \text{otherwise}\end{cases}\)

因此,\(x_0=a_it_iM_i\) 一定是原方程组的解。

由于 \(m_i\) 两两互质,所以 \(x=M \mod x_0\)。

BSGS

基础版:给定正整数 \(a,b,p\),保证 \(a,p\) 互质,求最小非负整数 \(x\),使得 \(a^x \equiv b \pmod p\)

令 \(x=A \lceil \sqrt{p} \rceil - B\),其中 \(0 \le A,B \le \sqrt{p}\),则有 \(a^{A \lceil \sqrt{p} \rceil - B} \equiv b \pmod p\)。把 \(b\) 移到同余式右面去得:\(a^{A \lceil \sqrt{p} \rceil} \equiv ba^B \pmod p\)。

由于已知 \(a,b\),故可以 \(O(\sqrt{p})\) 枚举 \(ba^B\) 的所有取值,用哈希存下来(map 也行,但是会多一个 \(\log\))。然后 \(O(\sqrt{p})\) 枚举 \(a^{A \lceil \sqrt{p} \rceil}\) 的所有取值,比较两者是否同余,就可以得到所有的 \(x\)。

整除分块

主要解决含有 \(\lfloor \frac{n}{i} \rfloor\) 的求和式子。

引理2:当 \(\lfloor\frac{n}{i}\rfloor=\lfloor\frac{n}{j}\rfloor\) 时,\(j_{\max}=\lfloor\frac{n}{\lfloor\frac{n}{i}\rfloor}\rfloor\)

引理3:\(\forall n \in N_+, |\{ \lfloor \frac{n}{d} \rfloor |d \in N_+,d \le n \}| \le 2 \sqrt{n}\)

证明见 oi-wiki


根据引理 1,原式可化为 \(G(n,k)=nk-\sum\limits_{i=1}^{n}i \lfloor \frac{k}{i} \rfloor\)

这个求和 \(\sum\limits_{i=1}^{n} \lfloor \frac{k}{i} \rfloor\) 可以整除分块搞。

注意到很多值是一样的,而且呈块分布。左端点 \(l\) 就是上一个块的右端点 +1,根据引理 2,块的右端点 \(r\) 就是 \(\min{(\lfloor\frac{k}{\lfloor\frac{k}{l}\rfloor}\rfloor,n)}\)。

对了,别忘了特判最后那一堆 0 的块(不然会出现除数是 0 的情况),它的右端点是 \(n\)。

ans=n*k;
	for(l=1;l<=n;l=r+1){
		if(k/l!=0) r=min(k/(k/l),n); 
		else r=n;
		ans-=(((l+r)*(r-l+1)/2)*(k/l));
	}
	cout<<ans<<endl;

积性函数

定义:定义域为 \(N_+\) 的函数 \(f(x)\) 若满足 \(a,b\) 互质时 \(f(ab)=f(a)f(b)\),则称 \(f(x)\) 为积性函数。

显然,若 \(f(x)\) 为积性函数,则有 \(f(1)=1\)。

性质:若 \(f(x)\) 为积性函数,则 \(f(x)=\prod p_i^{e_i}\)

所有积性函数都可以用类似于线性筛的方法求出。

常见积性函数

除数函数 \(\sigma_k(n)=\sum_{d|n}d^k\)

欧拉函数 \(\phi(n)\)

莫比乌斯函数 \(\mu(n)=\begin{cases}1, n=1 \\0, \exists d:d^2 \mid n\\(-1)^{\phi(n)},n=p_1p_2...p_m(p_i \space is \space a \space prime)\end{cases}\)

dalao的博文:https://blog.bill.moe/multiplicative-function-sieves-notes/

标签:lfloor,phi,frac,SDSC2021,long,Day1,rfloor,mod
来源: https://www.cnblogs.com/Gokix/p/SDSC2021_Day1.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有