判断质数
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 定义
-
若整数 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). a≡b(mod m).
-
对于 ∀ a ∈ [ 0 , m − 1 ] , \forall a \in [0,m-1], ∀a∈[0,m−1],集合 { a + k m } ( k ∈ Z ) \{a+km\}(k \in \mathbb{Z}) {a+km}(k∈Z)的所有数模m同余 , , ,余数都是 a , a, a,该集合称为一个模m的同余类 , , ,简记为 a ‾ . \overline a . a.
-
对于正整数 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,......,rm−2,rm−1,rm个同余类 , , ,且两两模 m m m不同余 , , ,这些同余类所组成的集合叫做模 m m m的完全剩余系 . . .
-
对于模 m m m的完全剩余系从中选出与 m m m互素的同余类元素 , , ,且这些元素模 m m m两两不同余 , , ,组成模 m m m的一个简化剩余系 , , ,最终得到的剩余系中元素个数为 φ ( m ) . \varphi(m). φ(m).
2.0 性质
-
简化剩余系关于模 m m m乘法封闭 . . .这是因为若 a , b ( 0 < a , b ≤ m ) a,b (0\lt a,b\le m) a,b(0<a,b≤m)与 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 a∗b与 m m m也无相同因子 , , ,故 a ∗ b a*b a∗b与 m m m互质,所以 a ∗ b m o d m a*b~mod~m a∗b mod m也属于 m m m的简化剩余系 . . .
-
欧拉定理 : : :
若正整数 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), a∗ai≡a∗aj(mod n),则 a ∗ ( a i − a j ) ≡ 0 ( m o d n ) . a*(a_i-a_j)\equiv 0(mod n). a∗(ai−aj)≡0(modn).因为 a , n a,n a,n互质 , , ,所以 a i ≡ a j ( m o d n ) . a_i\equiv a_j(mod~n). ai≡aj(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 ,ai∗a,aj∗a代表了不同的同余类.
又因为简化剩余系关于模 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)a1a2⋯aφ(n)≡(aa1)(aa2)⋯(aaφ(n))≡a1a2⋯aφ(n)(modn)
同除
a
1
a
2
⋯
a
φ
(
n
)
a_1a_2\cdots a_{\varphi(n)}
a1a2⋯aφ(n)得:
a
φ
(
n
)
=
1
(
m
o
d
n
)
a^{\varphi(n)}=1(mod~n)
aφ(n)=1(mod n)
- 欧拉定理的推论
若正整数 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)}. ab≡ab 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)}. ab≡ab 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 ∴a∗x+b∗y=gcd(a,b)=gcd(b,a mod b)=b∗tx+(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=a−⌊a/b⌋∗b
∴ 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 ∴a∗x+b∗y=b∗tx+(a−⌊a/b⌋∗b)∗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) ∴a∗x+b∗y=a∗ty+b∗(tx−⌊a/b⌋∗ty)
∴ x = t y , y = t x − ⌊ a / b ⌋ ∗ t y \therefore x=ty,y=tx-\lfloor a/b\rfloor *ty ∴x=ty,y=tx−⌊a/b⌋∗ty
∴ a ∗ 1 + 0 ∗ 0 = g c d ( a , 0 ) \therefore a*1+0*0=gcd(a,0) ∴a∗1+0∗0=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 ∴a∗x+b∗y=gcd(a,b)=gcd(b,a mod b)=b∗tx+(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=a−⌊a/b⌋∗b
∴ 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 ∴a∗x+b∗y=b∗tx+(a−⌊a/b⌋∗b)∗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) ∴a∗x+b∗y=a∗ty+b∗(tx−⌊a/b⌋∗ty)
∴ x = t y , y = t x − ⌊ a / b ⌋ ∗ t y \therefore x=ty,y=tx-\lfloor a/b\rfloor *ty ∴x=ty,y=tx−⌊a/b⌋∗ty
现已知 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 ∀d∈Q,那么一定有 a ( x 1 + d b ) + b ( y 1 − d a ) = c . a(x_1+db)+b(y_1-da)=c. a(x1+db)+b(y1−da)=c.
其中 ( x 1 + d b ) , ( y 1 − d a ) ∈ Z . (x_1+db),(y_1-da)\in Z. (x1+db),(y1−da)∈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). k∈Z).
( 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=bc−axmin
{ 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=ac−bymin
一个易错点 , , , 在 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=b2−b1(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 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} ⎣⎢⎢⎢⎡10⋮001⋮0⋯⋯⋱00001⎦⎥⎥⎥⎤
任何宽 ( m ) (m) (m)与其长 ( n ) (n) (n)相等的矩阵与其相乘等于原矩阵 . . .
- 转移矩阵和状态矩阵
以 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)=[Fibn−1,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,Fibn−1+Fibn]=[Fibn−1,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;
}