数学专题

本文详细介绍了数学和算法中的几个关键概念:欧拉函数的计算方法,包括线性筛和递推式;欧拉定理及其推论,阐述了它们在模运算中的应用;扩展欧几里得算法的证明和应用;以及矩阵乘法的定义和特殊矩阵如单位矩阵、转移矩阵和状态矩阵。这些基础知识在数论和计算机科学中具有重要地位。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

判断质数

1.0 O ( n ) O(\sqrt n) O(n )做法

inline bool Check(const int&num)
{
	for(register int i=2;i*i<=num;++i)//n+1防止C++取整出错 
		if(num%i==0)return false;
	return true;
}

2.0 线性筛素数

bool Visit[101000];
int Prime[21000],cnt;
inline void GetPrime(const int&size)
{
	memset(Visit,false,sizeof(bool)*(size+1));cnt=0;
	Visit[0]=Visit[1]=true;
	for(int i=2;i<=size;i++)
	{
		if(!Visit[i])
			Prime[++cnt]=i;
		for(int j=1;j<=cnt;j++)
		{
			if(Prime[j]*i>size)break;
			Visit[Prime[j]*i]=true;
			if(i%Prime[j])break;
		}
	}
}

欧拉函数

1.0 O ( n ) O(\sqrt n) O(n )做法

inline int Phi(int n)
{
	int ans=n;
	for(int i=2;i*i<=n;i++)//小心类型溢出
		if(n%i==0)
		{
			ans=ans/i*(i-1);
			while(n%i==0)n/=i;
		}
	if(n>1)ans=ans/n*(n-1);
	return ans;
}

2.0 线性筛递推 φ ( n ) \varphi(n) φ(n)

线性筛法能递推欧拉函数是因为欧拉函数是积性函数 . . .

inline void GetPrime(const int&size)
{
	memset(Visit,false,sizeof(bool)*(size+1));cnt=0;
	Visit[0]=Visit[1]=true;Phi[1]=1;
	for(int i=2;i<=size;i++)
	{
		if(!Visit[i])
			Prime[++cnt]=i,
			Phi[i]=i-1;
		for(int j=1;j<=cnt;j++)
		{
			if(Prime[j]*i>size)break;
			Visit[Prime[j]*i]=true;
			if(i%Prime[j]==0)
			{
				Phi[i*Prime[j]]=Phi[i]*Prime[j];
				break;
			}
			Phi[i*Prime[j]]=Phi[i]*(Prime[j]-1);
		}
	}
}

欧拉定理及其推论

0.0 前言

此篇内容大部分来自<<算法竞赛进阶指南>> By 李煜东

1.0 定义

  1. 若整数 a a a和整数 b b b初一正整数 m m m的余数相等 , , ,则称 a , b a,b a,b m m m同余 , , ,记为 a ≡ b ( m o d   m ) . a\equiv b(mod~m). ab(mod m).

  2. 对于 ∀ a ∈ [ 0 , m − 1 ] , \forall a \in [0,m-1], a[0,m1],集合 { a + k m } ( k ∈ Z ) \{a+km\}(k \in \mathbb{Z}) {a+km}(kZ)的所有数模m同余 , , ,余数都是 a , a, a,该集合称为一个模m的同余类 , , ,简记为 a ‾ . \overline a . a.

  3. 对于正整数 m , m, m, r 1 , r 2 , r 3 , . . . . . . , r m − 2 , r m − 1 , r m r_1,r_2,r_3,......,r_{m-2},r_{m-1},r_{m} r1,r2,r3,......,rm2,rm1,rm个同余类 , , ,且两两模 m m m不同余 , , ,这些同余类所组成的集合叫做模 m m m的完全剩余系 . . .

  4. 对于模 m m m的完全剩余系从中选出与 m m m互素的同余类元素 , , ,且这些元素模 m m m两两不同余 , , ,组成模 m m m的一个简化剩余系 , , ,最终得到的剩余系中元素个数为 φ ( m ) . \varphi(m). φ(m).

2.0 性质

  1. 简化剩余系关于模 m m m乘法封闭 . . .这是因为若 a , b ( 0 < a , b ≤ m ) a,b (0\lt a,b\le m) a,b(0<a,bm) m m m互质 , , , g c d ( a , m ) = g c d ( b , m ) = 1 , gcd(a,m)=gcd(b,m)=1, gcd(a,m)=gcd(b,m)=1,因为 a , b a,b a,b m m m都无相同因子 , , , a ∗ b a∗b ab m m m也无相同因子 , , , a ∗ b a*b ab m m m互质,所以 a ∗ b   m o d   m a*b~mod~m ab mod m也属于 m m m的简化剩余系 . . .

  2. 欧拉定理 : : :

若正整数 a , n a,n a,n互质 , , , a φ ( n ) = 1 ( m o d   n ) . a^{\varphi(n)}=1(mod~n). aφ(n)=1(mod n).

n n n的简化剩余系为 { a 1 ‾ , a 2 ‾ , ⋯   , a φ ( n ) ‾ } . \{\overline{a_1},\overline{a_2},\cdots,\overline{a_{\varphi(n)}}\}. {a1,a2,,aφ(n)}. ∀ a i , a j , \forall a_i,a_j, ai,aj, a ∗ a i ≡ a ∗ a j ( m o d   n ) , a*a_i\equiv a*a_j(mod~n), aaiaaj(mod n), a ∗ ( a i − a j ) ≡ 0 ( m o d n ) . a*(a_i-a_j)\equiv 0(mod n). a(aiaj)0(modn).因为 a , n a,n a,n互质 , , ,所以 a i ≡ a j ( m o d   n ) . a_i\equiv a_j(mod~n). aiaj(mod n).故当 a i ≠ a j a_i \not= a_j ai=aj , a i ∗ a , a j ∗ a ,a_i*a,a_j*a ,aia,aja代表了不同的同余类.

又因为简化剩余系关于模 n n n乘法封闭 , , , a a i ‾ \overline{aa_i} aai也在简化同余系集合中 . . .因此集合 { a 1 ‾ , a 2 ‾ , ⋯   , a φ ( n ) ‾ } \{\overline{a_1},\overline{a_2},\cdots,\overline{a_{\varphi(n)}}\} {a1,a2,,aφ(n)}和集合 { a a 1 ‾ , a a 2 ‾ , ⋯   , a a φ ( n ) ‾ } \{\overline{aa_1},\overline{aa_2},\cdots,\overline{aa_{\varphi(n)}}\} {aa1,aa2,,aaφ(n)}都能代表 n n n的简化剩余系 . . .

所以 : : :
a φ ( n ) a 1 a 2 ⋯ a φ ( n ) ≡ ( a a 1 ) ( a a 2 ) ⋯ ( a a φ ( n ) ) ≡ a 1 a 2 ⋯ a φ ( n ) ( m o d n ) a^{\varphi(n)}a_1a_2\cdots a_{\varphi(n)}\equiv(aa_1)(aa_2)\cdots(aa_{\varphi(n)})\equiv a_1a_2\cdots a_{\varphi(n)}(mod n) aφ(n)a1a2aφ(n)(aa1)(aa2)(aaφ(n))a1a2aφ(n)(modn)
同除 a 1 a 2 ⋯ a φ ( n ) a_1a_2\cdots a_{\varphi(n)} a1a2aφ(n)得:
a φ ( n ) = 1 ( m o d   n ) a^{\varphi(n)}=1(mod~n) aφ(n)=1(mod n)

  1. 欧拉定理的推论

若正整数 a , n a,n a,n互质,则对于任意正整数 b , b, b, a b ≡ a b   m o d   φ ( n ) . a^b\equiv a^{b~mod~\varphi(n)}. abab mod φ(n).

特别地 , , , a , n a,n a,n不一定互质且 b > φ ( n ) b>\varphi(n) b>φ(n) , , , a b ≡ a b   m o d   φ ( n ) + φ ( n ) . a^b\equiv a^{b~mod~\varphi(n)+\varphi(n)}. abab mod φ(n)+φ(n).

拓展欧几里德

1.0 证明

a x + b y = g c d ( a , b ) ax+by=gcd(a,b) ax+by=gcd(a,b)

∵ g c d ( b , a   m o d   b ) = g c d ( a , b ) \because gcd(b,a~mod~b)=gcd(a,b) gcd(b,a mod b)=gcd(a,b)

∴ a ∗ x + b ∗ y = g c d ( a , b ) = g c d ( b , a   m o d   b ) = b ∗ t x + ( a   m o d   b ) ∗ t y \therefore a*x+b*y=gcd(a,b)=gcd(b,a~mod~b)=b*tx+(a~mod~b)*ty ax+by=gcd(a,b)=gcd(b,a mod b)=btx+(a mod b)ty

∵ a   m o d   b = a − ⌊ a / b ⌋ ∗ b \because a~mod~b=a-\lfloor a/b\rfloor*b a mod b=aa/bb

∴ a ∗ x + b ∗ y = b ∗ t x + ( a − ⌊ a / b ⌋ ∗ b ) ∗ t y \therefore a*x+b*y=b*tx+(a-\lfloor a/b\rfloor*b)*ty ax+by=btx+(aa/bb)ty

∴ a ∗ x + b ∗ y = a ∗ t y + b ∗ ( t x − ⌊ a / b ⌋ ∗ t y ) \therefore a*x+b*y=a*ty+b*(tx-\lfloor a/b\rfloor *ty) ax+by=aty+b(txa/bty)

∴ x = t y , y = t x − ⌊ a / b ⌋ ∗ t y \therefore x=ty,y=tx-\lfloor a/b\rfloor *ty x=ty,y=txa/bty

∴ a ∗ 1 + 0 ∗ 0 = g c d ( a , 0 ) \therefore a*1+0*0=gcd(a,0) a1+00=gcd(a,0)

用数学归纳法证明

( f r o m (from (from lb学长 ) ) )

a x + b y = g c d ( a , b ) ax+by=gcd(a,b) ax+by=gcd(a,b)

∵ g c d ( b , a   m o d   b ) = g c d ( a , b ) \because gcd(b,a~mod~b)=gcd(a,b) gcd(b,a mod b)=gcd(a,b)

∴ a ∗ x + b ∗ y = g c d ( a , b ) = g c d ( b , a   m o d   b ) = b ∗ t x + ( a   m o d   b ) ∗ t y \therefore a*x+b*y=gcd(a,b)=gcd(b,a~mod~b)=b*tx+(a~mod~b)*ty ax+by=gcd(a,b)=gcd(b,a mod b)=btx+(a mod b)ty

∵ a   m o d   b = a − ⌊ a / b ⌋ ∗ b \because a~mod~b=a-\lfloor a/b\rfloor*b a mod b=aa/bb

∴ a ∗ x + b ∗ y = b ∗ t x + ( a − ⌊ a / b ⌋ ∗ b ) ∗ t y \therefore a*x+b*y=b*tx+(a-\lfloor a/b\rfloor*b)*ty ax+by=btx+(aa/bb)ty

∴ a ∗ x + b ∗ y = a ∗ t y + b ∗ ( t x − ⌊ a / b ⌋ ∗ t y ) \therefore a*x+b*y=a*ty+b*(tx-\lfloor a/b\rfloor *ty) ax+by=aty+b(txa/bty)

∴ x = t y , y = t x − ⌊ a / b ⌋ ∗ t y \therefore x=ty,y=tx-\lfloor a/b\rfloor *ty x=ty,y=txa/bty

现已知 a x + b y = g c d ( a , b ) ax+by=gcd(a,b) ax+by=gcd(a,b)的一组特解 , , ,记为 x 0 , y 0 . x_0,y_0. x0,y0.

则有 a x 0 c g c d ( a , b ) + b y 0 c g c d ( a , b ) = c . a\frac{x_0c}{gcd(a,b)}+b\frac{y_0c}{gcd(a,b)}=c. agcd(a,b)x0c+bgcd(a,b)y0c=c.

x 1 = x 0 c g c d ( a , b ) , y 1 = y 0 c g c d ( a , b ) . x_1=\frac{x_0c}{gcd(a,b)},y_1=\frac{y_0c}{gcd(a,b)}. x1=gcd(a,b)x0c,y1=gcd(a,b)y0c.

不妨设 ∀ d ∈ Q \forall d\in Q dQ,那么一定有 a ( x 1 + d b ) + b ( y 1 − d a ) = c . a(x_1+db)+b(y_1-da)=c. a(x1+db)+b(y1da)=c.

其中 ( x 1 + d b ) , ( y 1 − d a ) ∈ Z . (x_1+db),(y_1-da)\in Z. (x1+db),(y1da)Z.

d d d取最小可能正值时 , , , d x = d b , d y = d a , d_x=db,d_y=da, dx=db,dy=da,任意解与 x 1 , y 1 x_1,y_1 x1,y1的偏差显然为 d x , d y d_x,d_y dx,dy的倍数 . . .

那么显然最小 d = 1 g c d ( a , b ) , d=\frac1{gcd(a,b)}, d=gcd(a,b)1,

通解形式为 x = x 1 + k b g c d ( a , b ) , y = y 1 + k a g c d ( a , b ) . ( k x=x_1+\frac{kb}{gcd(a,b)},y=y_1+\frac{ka}{gcd(a,b)}.(k x=x1+gcd(a,b)kb,y=y1+gcd(a,b)ka.(k为常数 k ∈ Z ) . k\in Z). kZ).

( f r o m (from (from xaocy ) ) )

A = a g c d ( a , b ) , B = b g c d ( a , b ) A=\frac{a}{gcd(a,b)},B=\frac{b}{gcd(a,b)} A=gcd(a,b)a,B=gcd(a,b)b显然 : : :

{ x m i n = ( x 1 % B + B ) % B y m a x = c − a x m i n b \begin{cases} & x_{min}=(x_1\%B+B)\%B\\ & y_{max}=\frac{c-ax_{min}}{b} \end{cases} {xmin=(x1%B+B)%Bymax=bcaxmin

{ y m i n = ( y 1 % A + A ) % A x m a x = c − b y m i n a \begin{cases} & y_{min}=(y_1\%A+A)\%A\\ & x_{max}=\frac{c-by_{min}}{a} \end{cases} {ymin=(y1%A+A)%Axmax=acbymin

一个易错点 , , , E x g c d Exgcd Exgcd , a ,a ,a b b b 都不能为负数 , , , 可以通过适当的变换使 a a a b b b 变成正数 , , , 比如把负号转移到要求的 x x x y y y . . .

2.0 Caioj1153

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
inline long long Gcd(long long a,long long b)
{
	if(b==0)return a;
	return Gcd(b,a%b);
}
inline void ExGcd(long long a,long long b,long long&x,long long&y)
{
	if(b==0){x=1,y=0;return;}
	ExGcd(b,a%b,y,x);y=y-(a/b)*x;
}
long long a,b,x,y,k;
int main()
{
	scanf("%lld%lld%lld",&a,&b,&k);
	register long long d=Gcd(a,b);
	if(k%d){puts("no solution!");}
	else
	{
		ExGcd(a,b,x,y);
		printf("%lld %lld",x*k/d,y*k/d);
	}
	return 0;
}

3.0 Caioj1155

P = b 1 ( m o d   m 1 ) P = b 2 ( m o d   m 2 ) k m 1 + b 1 = P ( m o d   m 1 ) l m 2 + b 2 = P ( m o d   m 2 ) k m 1 + b 1 = l m 2 + b 2 ( m o d    l c m ( m 1 , m 2 ) ) k m 1 + ( − l ) m 2 = b 2 − b 1 ( m o d    l c m ( m 1 , m 2 ) ) P=b_1(mod~m_1)\\ P=b_2(mod~m_2)\\ km_1+b_1=P(mod~m_1)\\ lm_2+b_2=P(mod~m_2)\\ km_1+b_1=lm_2+b_2(mod~~lcm(m_1,m_2))\\ km_1+(-l)m_2=b_2-b_1(mod~~lcm(m_1,m_2)) P=b1(mod m1)P=b2(mod m2)km1+b1=P(mod m1)lm2+b2=P(mod m2)km1+b1=lm2+b2(mod  lcm(m1,m2))km1+(l)m2=b2b1(mod  lcm(m1,m2))

设得到的解为 k 0 , k_0, k0, : : :

P = k 0 m 1 + b 1 ( m o d    l c m ( m 1 , m 2 ) ) P=k_0m_1+b_1(mod~~lcm(m_1,m_2)) P=k0m1+b1(mod  lcm(m1,m2))

剩下的东西大家懂得都懂 . . .

inline long long Gcd(const long long&a,const long long&b)
{
	if(b==0)return a;
	return Gcd(b,a%b);
}
inline void ExGcd(const long long&a,const long long&b,long long&x,long long&y)
{
	if(b==0){x=1,y=0;return;}
	ExGcd(b,a%b,y,x);y-=(a/b)*x;
}
long long b1,b2,m1,m2,g,x,y;
int n;
int main()
{
	scanf("%d",&n);
	scanf("%lld%lld",&b1,&m1);
	bool Is=true;
	for(int i=2;i<=n;i++)
	{
		scanf("%lld%lld",&b2,&m2);
		//Ax+By=C,A=m1,B=-m2,C=b2-b1
		g=Gcd(m1,m2);
		if((b2-b1)%g)
		{
			Is=false;
			for(int j=i+1;j<=n;j++)
				scanf("%lld%lld",&b2,&m2);
			break;
		}
		ExGcd(m1,m2,x,y);
		x*=(b2-b1)/g;
		x=(x%(m2/g)+m2/g)%(m2/g);
		b1=x*m1+b1;
		m1=m1*m2/g;
	}
	if(Is)printf("%lld",b1);
	return 0;
}

矩阵乘法

1.0 定义

struct Matrixes
{
	unsigned long long Arr[3][3];
	int n,m;
	Matrixes(){memset(Arr,0,sizeof(Arr));}
	inline friend Matrixes operator*(const Matrixes&a,const Matrixes&b)
	{
		Matrixes c;
		for(register int i=1;i<=a.n;i++)
			for(register int j=1;j<=b.n;j++)
				for(register int k=1;k<=a.m;k++)
					c.Arr[i][j]=(c.Arr[i][j]+a.Arr[i][k]*b.Arr[k][j])%Mod;
		c.n=a.n;c.m=b.n;
		return c;
	}
};

2.0 特殊矩阵

  1. 单位矩阵

[ 1 0 ⋯ 0 0 1 ⋯ 0 ⋮ ⋮ ⋱ 0 0 0 0 1 ] \begin{bmatrix} 1&0&\cdots&0\\ 0&1&\cdots&0\\ \vdots&\vdots&\ddots&0\\ 0&0&0&1 \end{bmatrix} 10001000001

任何宽 ( m ) (m) (m)与其长 ( n ) (n) (n)相等的矩阵与其相乘等于原矩阵 . . .

  1. 转移矩阵和状态矩阵

F i b o n a c c i Fibonacci Fibonacci数列为例 , , ,

设状态矩阵 F ( n ) = [ F i b n − 1 , F i b n ] F(n)=[Fib_{n-1},Fib_n] F(n)=[Fibn1,Fibn]

[ F i b n , F i b n + 1 ] = [ F i b n , F i b n − 1 + F i b n ] = [ F i b n − 1 , F i b n ] [ 0 1 1 1 ] \begin{matrix} & [Fib_n,Fib_{n+1}]\\ & =[Fib_n,Fib_{n-1}+Fib_n]\\ & =[Fib_{n-1},Fib_n] \begin{bmatrix} 0&1\\ 1&1 \end{bmatrix} \end{matrix} [Fibn,Fibn+1]=[Fibn,Fibn1+Fibn]=[Fibn1,Fibn][0111]

利用递推式间的和差关系能推出转移矩阵 . . .

3.0 Acwing206

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
struct Matrixes
{
	long long Arr[70][70];int n,m;
	Matrixes(int wide=0)
	{
		n=m=wide;
		memset(Arr,0,sizeof(Arr));
		for(int i=1;i<=wide;i++)
			Arr[i][i]=1;
	}
	long long *operator[](int idx){return Arr[idx];}
	inline friend Matrixes operator*(Matrixes a,Matrixes b)
	{
		Matrixes c;
		for(register int i=1;i<=a.n;i++)
			for(register int j=1;j<=b.n;j++)
				for(register int k=1;k<=a.m;k++)
					c[i][j]+=(a[i][k]*b[k][j]);
		c.n=a.n;c.m=b.n;
		return c;
	}
};Matrixes Arr[65],Ans;
inline Matrixes Pow(Matrixes a,int n)
{
	Matrixes r(a.n);
	while(n)
	{
		if(n&1)r=r*a;
		a=a*a;n>>=1;
	}
	return r;
}
int n,m,t,act;
inline int Hash(int i,int j){return (i-1)*m+j+1;}
char St[10][10];
char Opt[10][10];
int len[10];
int main()
{
	scanf("%d%d%d%d",&n,&m,&t,&act);
	for(int i=1;i<=n;i++)
		scanf("%s",St[i]+1);
	for(int i=1;i<=act;i++)
		scanf("%s",Opt[i]+1),len[i]=strlen(Opt[i]+1);
	Ans[1][1]=1;Ans.n=1;
	Ans.m=n*m+1;
	for(int i=1;i<=60;i++)
	{
		Arr[i][1][1]=1;
		Arr[i].n=Arr[i].m=n*m+1;
		for(int j=1;j<=n;j++)
			for(int k=1;k<=m;k++)
			{
				int pos=St[j][k]-48+1;
				char opt=Opt[pos][(i-1)%len[pos]+1];
				if(opt>='0'&&opt<='9')
					Arr[i][1][Hash(j,k)]=opt-48,
					Arr[i][Hash(j,k)][Hash(j,k)]=1;//留着这些数 
				else if(opt=='N'&&j>1)
					Arr[i][Hash(j,k)][Hash(j-1,k)]=1;//把 Hash(j,k)乘到Hash(j-1,k)去 
				else if(opt=='W'&&k>1)
					Arr[i][Hash(j,k)][Hash(j,k-1)]=1;
				else if(opt=='S'&&j<n)
					Arr[i][Hash(j,k)][Hash(j+1,k)]=1;
				else if(opt=='E'&&k<m)
					Arr[i][Hash(j,k)][Hash(j,k+1)]=1;
			}
	}
	Matrixes tmp(n*m+1);
	for(int i=1;i<=60;i++)tmp=tmp*Arr[i];
	Ans=Ans*Pow(tmp,t/60);
	for(int i=1;i<=t%60;i++)Ans=Ans*Arr[i];
	long long ans=0;
	for(int i=2;i<=n*m+1;i++)ans=max(ans,Ans[1][i]);
	printf("%lld\n",ans);
	return 0;
}

高斯消元

1.0 Luogu P2455 [SDOI2006]线性方程组

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
struct Matrixes
{
	double Arr[55][55];int n,m;
	inline double* operator[](const int&idx){return Arr[idx];}
	Matrixes(int wide=0)
	{
		n=m=wide;
		memset(Arr,0,sizeof(Arr));
		for(register int i=1;i<=wide;i++)
			Arr[i][i]=1.0;
	}
};Matrixes A;
int n;
int main()
{
	scanf("%d",&n);
	for(register int i=1;i<=n;++i)
		for(register int j=1;j<=n+1;j++)
			scanf("%lf",&A[i][j]);
	int now=1;//在哪条方程 
	for(register int i=1;i<=n;i++)//现在找到哪个元 
	{
		register int maxi=now;
		for(register int j=now+1;j<=n;j++)
			if(fabs(A[j][i])>fabs(A[maxi][i]))maxi=j;
		if(!A[maxi][i])continue;//这条方程无解不慌,找下一个元 
		for(register int j=1;j<=n+1;j++)
			swap(A[now][j],A[maxi][j]);//给他换上来 
		for(register int j=1;j<=n;j++)
		{
			if(j==now)continue;
			register double tmp=A[j][i]/A[now][i];//这的意思就是i这元在第j条方程里必为零 
			for(register int k=i+1;k<=n+1;k++)
				A[j][k]-=A[now][k]*tmp;
		}
		++now;
	}
	if(now<=n)
	{
		while(now<=n)
			if(A[now++][n+1]!=0)return puts("-1"),0;//老子这都没元了,还不等于零,无解了 
		return puts("0"),0;
	}
	for(register int i=1;i<=n;i++)
		printf("x%d=%.2lf\n",i,A[i][n+1]/A[i][i]+1e-9);
	return 0;
}

2.0 Acwing207

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
struct Matrixes
{
	double Arr[25][25];int n,m;
	inline double* operator[](const int&idx){return Arr[idx];}
	Matrixes(int wide=0)
	{
		n=m=wide;
		memset(Arr,0,sizeof(Arr));
		for(register int i=1;i<=wide;i++)
			Arr[i][i]=1.0;
	}
};
inline int Gauss(Matrixes&A,int n)
{
	int now=1;//在哪条方程 
	for(register int i=1;i<=n;i++)//现在找到哪个元 
	{
		register int maxi=now;
		for(register int j=now+1;j<=n;j++)
			if(fabs(A[j][i])>fabs(A[maxi][i]))maxi=j;
		if(!A[maxi][i])continue;//这条方程无解不慌,找下一个元 
		for(register int j=1;j<=n+1;j++)
			swap(A[now][j],A[maxi][j]);//给他换上来 
		for(register int j=1;j<=n;j++)
		{
			if(j==now)continue;
			register double tmp=A[j][i]/A[now][i];//这的意思就是i这元在第j条方程里必为零 
			for(register int k=i+1;k<=n+1;k++)
				A[j][k]-=A[now][k]*tmp;
		}
		++now;
	}
	if(now<=n)
	{
		while(now<=n)
			if(A[now++][n+1]!=0)return -1;//老子这都没元了,还不等于零,无解了 
		return 0;
	}
	return 1;
}
inline double Sqr(const double&x){return x*x;}
Matrixes Arr,Qry;
int n;
int main()
{
	scanf("%d",&n);
	for(int i=1;i<=n+1;i++)
		for(int j=1;j<=n;j++)
			scanf("%lf",&Arr[i][j]);
	for(int i=1;i<=n;i++)
	{
		//Qry[i][n+1]=0.0;
		for(int j=1;j<=n;j++){
			Qry[i][j]=2.0*(Arr[i][j]-Arr[i+1][j]),
			Qry[i][n+1]+=Sqr(Arr[i][j])-Sqr(Arr[i+1][j]);}
	}
	Gauss(Qry,n);
	for(int i=1;i<=n;i++)
		printf("%.3lf ",Qry[i][n+1]/Qry[i][i]);
	return 0;
}

3.0 Acwing208

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int Arr[110],n,t,ans,T,x,y;
int main()
{
	scanf("%d",&T);
	for(register int Test=1;Test<=T;Test++)
	{
		scanf("%d",&n);
		for(register int i=1;i<=n;i++)
			scanf("%d",&Arr[i]);
		for(register int i=1;i<=n;i++)
		{
			scanf("%d",&x);
			Arr[i]^=x;//结束的状态和开始的状态有关,现在变成了需要的操作,等式右变成0 
			Arr[i]|=1<<i;//Arr[i][i]=1,按自己,自己也会变 
		}
		while(~scanf("%d%d",&x,&y)&&x&&y)
			Arr[y]|=1<<x;//Arr[y][x]=1,按x,y也会变 
		ans=1;
		for(int i=1;i<=n;i++)
		{
			for(int j=i+1;j<=n;j++)
				if(Arr[j]>Arr[i])
					swap(Arr[i],Arr[j]);
					//找主元位最高的Arr[i] 其实就是一个一个元地消 
			if(Arr[i]==0){ans=1<<(n-i+1);break;}
			if(Arr[i]==1){ans=0;break;}
			//消去其他该位的系数 
			for(int k=n;k>=1;k--)
				if(Arr[i]>>k&1)
				{
					for(int j=1;j<=n;j++)
						if(i!=j&&(Arr[j]>>k&1))
							Arr[j]^=Arr[i];
					break;
				}
		}
		if(ans==0)puts("Oh,it's impossible~!!");
		else printf("%d\n",ans);
	}
	return 0;
}

4.0 Acwing209

精度坑 , , ,贪心细节坑 , , ,性能要求低尽量用这个

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
const double Eps=1e-8;
long double Arr[510][510];
long long Cost[510],ans;
int n,m;
int main()
{
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;i++)
		for(int j=1;j<=m;j++)
			scanf("%Lf",&Arr[i][j]);
	for(int i=1;i<=n;i++)
		scanf("%lld",&Cost[i]);
	int now=1;
	for(int i=1;i<=m;i++)
	{
		int maxi=0;
		for(int j=now;j<=n;j++)
			if(fabs(Arr[j][i])>Eps&&(maxi==0||Cost[j]<Cost[maxi]))maxi=j;
		if(maxi==0)continue;
		ans+=Cost[maxi];
		for(int j=1;j<=m;j++)
			swap(Arr[now][j],Arr[maxi][j]);
		swap(Cost[now],Cost[maxi]);
		for(int j=1;j<=n;j++)
		{
			if(j!=now&&fabs(Arr[j][i])>Eps)
			{
				long double tmp=Arr[j][i]/Arr[now][i];
				for(int k=i;k<=m;k++)
					Arr[j][k]-=tmp*Arr[now][k];
			}
		}
		now++;
	}
	printf("%d %lld",now-1,ans);
	return 0;
}

5.0 Acwing210

异或空间

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int MaxN=10005;
unsigned long long Arr[MaxN];
int n,m;
int main()
{
	int Task;scanf("%d",&Task);
	for(int Case=1;Case<=Task;Case++)
	{
		printf("Case #%d:\n",Case);
		scanf("%d",&n);
		for(int i=1;i<=n;i++)
			scanf("%llu",&Arr[i]);
		int tmp=n;
		bool zero=false;
		for(int i=1;i<=n;i++)
		{
			for(int j=i+1;j<=n;j++)
				if(Arr[j]>Arr[i])swap(Arr[i],Arr[j]);
			if(Arr[i]==0){zero=true;tmp=i-1;break;}//有零行,记录一下,基底是1~i-1 
			for(int k=63;k>=0;k--)
				if(Arr[i]>>k&1)
				{
					for(int j=1;j<=n;j++)
						if(i!=j&&(Arr[j]>>k&1))Arr[j]^=Arr[i];
					break;
				}
		}
		scanf("%d",&m);
		while(m--)
		{
			unsigned long long k,ans=0;
			scanf("%llu",&k);
			if(zero)k--;//跳过零 
			if(k>=(1llu<<tmp))puts("-1");//只有0~2^tmp-1种选择 
			else
			{
				for(int i=tmp-1;i>=0;i--)
					if(k>>i&1)ans^=Arr[tmp-i];
				//只有0~2^tmp-1中选择,那k的二进制是什么,
                //就使其异或二进制位所对的值
				//说白了
				//如果问的是第3名
				//1001 
				//0101 
				//0010 
				//0000 
				//0000
				//那就异或 0101 0010->0111 
				//后面的自由元影响不了前面二进制位的排名 
				printf("%llu\n",ans);
			}
		}
	}
	return 0;
}

莫比乌斯函数

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值