各种数学知识4
1.行列式(从原来的线性代数那里搬过来的)
$n$阶行列式形如一个$n*n$的矩阵,其值为所有取自不同行不同列的$n$个元素的$n!$项乘积
$a_{1,p_1}a_{2,p_2}a_{3,p_3}......a_{n,p_n}$(一项乘积)
...的代数和
其中$p_1p_2p_3......p_n$是$1->n$的一个排列,当这个排列中的逆序对为偶数对时这项乘积带正号,当这个排列中的逆序对为奇数对时这项乘积带负号。
将一个$n$阶行列式的第$k(k∈N^*)$行与第$k$列同时去掉得到的新行列式称为这个行列式的$n-1$阶主子式
行列式的一些性质
①行列互换,行列式不变。
②把行列式中某一行(列)的所有元素都乘以一个数$x$,等于用数$x$乘以行列式。
③如果行列式的某行(列)的各元素是两个元素之和,那么这个行列式等于两个行列式的和。
④如果行列式中有两行(列)相同,那么行列式为零。(所谓两行(列)相同就是说两行(列)的对应元素都相等)
⑤如果行列式中两行(列)成比例,那么行列式为零。
⑥把一行(列)的倍数加到另一行(列),行列式不变。
⑦对换行列式中两行(列)的位置,行列式反号。
2.阶和原根
我们称在$p>1且gcd(x,p)==1$时满足$x^k \equiv 1(mod$ $p$的最小的$k$是$x$在模$p$剩余系下的阶,而原根可以看成是模意义下的对数
对原根的应用:SDOI2015序列统计

1 #include<cmath> 2 #include<cstdio> 3 #include<vector> 4 #include<cstring> 5 #include<algorithm> 6 #define o 1ll 7 #define vint vector<int> 8 using namespace std; 9 const int N=40005,mod=1004535809; 10 int n,m,x,s,G,Gi,rd,ort,md; vint odf; 11 int w[N],in[N],a[N],b[N],c[N],rev[N],pw[30][2]; 12 int Qpow(int x,int k,int m) 13 { 14 if(k==1) return x; 15 int tmp=Qpow(x,k>>1,m); 16 return 1ll*tmp*tmp%m*((k&1)?x:1)%m; 17 } 18 int Phi(int x) 19 { 20 int ret=x; 21 for(int i=2;i*i<=x;i++) 22 if(x%i==0) 23 { 24 ret/=i,ret*=i-1; 25 while(x%i==0) x/=i; 26 } 27 if(x!=1) ret/=x,ret*=x-1; 28 return ret; 29 } 30 int Ort(int x) 31 { 32 register int i,j; 33 int phi=Phi(x),tmp=phi,cnt=0; 34 for(i=2;i*i<=tmp;i++) 35 if(tmp%i==0) 36 { 37 w[++cnt]=i; 38 while(tmp%i==0) tmp/=i; 39 } 40 for(i=2;i<=x-1;i++) 41 { 42 bool pass=true; 43 for(j=1;j<=cnt;j++) 44 if(Qpow(i,phi/w[j],x)==1) 45 {pass=false; break;} 46 if(pass) return i; 47 } 48 return -1; 49 } 50 void Pre() 51 { 52 G=3,Gi=Qpow(3,mod-2,mod); 53 for(int i=1;i<=24;i++) 54 { 55 pw[i][0]=Qpow(G,(mod-1)/(1<<i),mod); 56 pw[i][1]=Qpow(Gi,(mod-1)/(1<<i),mod); 57 } 58 ort=Ort(m),md=Phi(m),odf.resize(m-1); 59 for(int i=0,t=1;i<m-1;i++) in[t]=i,t=o*t*ort%m; 60 } 61 void Trans(int *arr,int len,int typ) 62 { 63 register int i,j,k; 64 for(i=0;i<len;i++) 65 if(rev[i]>i) swap(arr[rev[i]],arr[i]); 66 for(i=2;i<=len;i<<=1) 67 { 68 int lth=i>>1,ort=pw[(int)log2(i)][typ==-1]; 69 for(j=0;j<len;j+=i) 70 { 71 int ori=1,tmp; 72 for(k=j;k<j+lth;k++,ori=1ll*ori*ort%mod) 73 { 74 tmp=1ll*ori*arr[k+lth]%mod; 75 arr[k+lth]=(arr[k]-tmp+mod)%mod; 76 arr[k]=(arr[k]+tmp)%mod; 77 } 78 } 79 } 80 if(typ==-1) 81 { 82 int Ni=Qpow(len,mod-2,mod); 83 for(i=0;i<=len;i++) 84 arr[i]=1ll*arr[i]*Ni%mod; 85 } 86 } 87 vint Merge(vint v1,vint v2) 88 { 89 register int i; 90 vint ret; ret.clear(); 91 int l1=v1.size(),l2=v2.size(),len=l1+l2; 92 for(i=0;i<l1;i++) a[i]=v1[i]; 93 for(i=0;i<l2;i++) b[i]=v2[i]; 94 int lth=1; while(lth<=len) lth<<=1; 95 for(i=0;i<=lth;i++) 96 rev[i]=(rev[i>>1]>>1)+(i&1)*(lth>>1); 97 Trans(a,lth,1),Trans(b,lth,1); 98 for(i=0;i<=lth;i++) c[i]=1ll*a[i]*b[i]%mod,a[i]=b[i]=0; 99 Trans(c,lth,-1),ret.resize(m-1); 100 for(i=0;i<=lth;i++) (ret[i%(m-1)]+=c[i])%=mod; 101 return ret; 102 } 103 vint Polypow(vint x,int k) 104 { 105 if(k==1) return x; 106 vint tmp=Polypow(x,k>>1); 107 tmp=Merge(tmp,tmp); 108 if(k&1) tmp=Merge(tmp,x); 109 return tmp; 110 } 111 int main() 112 { 113 scanf("%d%d%d%d",&n,&m,&x,&s),Pre(); 114 for(int i=1;i<=s;i++) 115 { 116 scanf("%d",&rd); 117 if(rd) odf[in[rd]]++; 118 } 119 // for(int i=0;i<m;i++) printf("%d ",odf[i]); 120 odf=Polypow(odf,n); 121 printf("%d",odf[in[x]]); 122 return 0; 123 }
我们说$x$是在模$p$剩余系下的原根,当且仅当$x^k(k∈[0,p-1])$遍历了这个剩余系
一个关于原根的定理:如果模$p$剩余系下有原根,则恰有$φ(φ(p))$个原根,不会证
如何检验原根
将$φ(p)$分解质因数得到质因数$pri_i$们,若所有$x^{\frac{φ(p)}{pri_i}}$在模$p$意义下都不为$1$,则这个数是模$p$意义下的原根,仍然不会证
求原根

1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 using namespace std; 5 const int N=10005; 6 int n,cnt,pw[N]; 7 int Qpow(int x,int k,int mod) 8 { 9 if(k==1) return x; 10 int tmp=Qpow(x,k>>1,mod); 11 return 1ll*tmp*tmp%mod*((k&1)?x:1)%mod; 12 } 13 int Phi(int x) 14 { 15 int ret=x; 16 for(int i=2;i*i<=x;i++) 17 if(x%i==0) 18 { 19 ret/=i,ret*=i-1; 20 while(x%i==0) x/=i; 21 } 22 if(x!=1) ret/=x,ret*=x-1; 23 return ret; 24 } 25 int Ort(int x) 26 { 27 register int i,j; 28 int phi=Phi(x),tmp=phi; 29 for(i=2,cnt=0;i*i<=tmp;i++) 30 if(tmp%i==0) 31 { 32 pw[++cnt]=i; 33 while(tmp%i==0) tmp/=i; 34 } 35 for(i=2;i<=x-1;i++) 36 { 37 bool pass=true; 38 for(j=1;j<=cnt;j++) 39 if(Qpow(i,phi/pw[j],x)==1) 40 {pass=false; break;} 41 if(pass) return i; 42 } 43 return -1; 44 } 45 int main() 46 { 47 int T=100; 48 while(T--) 49 { 50 scanf("%d",&n); 51 printf("%d\n",Ort(n)); 52 } 53 return 0; 54 }
3.FFT预备知识(懒得一个个写了)
复数
表示方式 ①$a+bi$(实+虚) ②$r(sinθ+cosθ)$(角度乘模长)
运算(以点值为例) 加减:对应$x,y$相加减(点值) 乘:模长相乘角度相加 除:写成分数后将分母“实数化”
(n次)单位根:$n$等分单位元的向量们(一定有一个是$(1,0)$)
一些性质
$ω_n=e^{2iπ/n}$ $ω_n^n=ω_n^0=1$ $ω_n^i*ω_n^j=ω_n^(i+j)$ $w_{dn}^{dk}=ω_n^k$(最后一个在约$\frac{n}{2}$就是FFT的关键了)
欧拉公式
$e^{ix}=cos$ $x+isin$ $x$
可以看做是单位圆上的向量的一种角度表达,所有复数可以类比地表示为$r*e^{iθ}$(模长乘角度)
一些奇怪的东西:
$cos(x)=\sum\limits_{i=0}^{∞}(i$ $is$ $even)$ $(-1)^{\frac{i}{2}}*\frac{x^i}{i!}$
$sin(x)=\sum\limits_{i=0}^{∞}(i$ $is$ $odd)$ $(-1)^{\frac{i}{2}}*\frac{x^i}{i!}$
4.拉格朗日插值
思路:针对每项构造,然后加起来
zrq写过一篇很好的博客(其实是我懒)
5.导数
函数在某一点的变化率,然后因为文化课并没学这里就放了一坨常见导数
常函数$y=b->y'=0$
一次函数$y=kx+b->y'=k$
二次函数$y=ax^2+bx+c->y'=ax+b$
指数函数$y=a^x->y'=a^x\ln a$
对数函数$y=\log_a x->y'=\frac{1}{x\ln a}$
幂函数$y=x^a->y'=ax^{a-1}$
三角函数$y=\sin x->y'=\cos x$ $y=\cos x->y'=-\sin x$ $y=\tan x->y'=\sec^2 x$
系数不消失,常数消失
导数的四则运算
加减:$(f±g)'=f'±g'$ 乘:$(f*g)'=f'*g+f*g'$ 除:转化为乘,于是多了一个$g^2$ $(\frac{f}{g})'=\frac{f'*g+f*g'}{g^2}$
一个多次函数的导数等于各次项的导数之和,原函数导数是反函数导数的倒数
k阶导数:一个函数的一阶导数就是它的导数,二阶导数就是它的导数的导数,依此类推
求导的链式法则:若$h(x)=f(g(x))$,则$h'(x)=f'(g(x))g'(x)$
6.泰勒展开
用多项式逼近函数,这样我们就可以从维护一个奇奇怪怪的函数变成维护多项式了
具体来说,令$d^k(x)$表示$f(x)$的k阶导数,若$f(x)$在$[a,b]$上的导数连续,那么取$x_0∈[a,b]$则有
$f(x)=f(x_0)+\sum\limits_{i=1}^∞ \frac{d^i(x_0)(x-x_0)^i}{i!}$
实际应用因为精度有限我们取上前十几项怎么也够了
然而知道什么是泰勒展开和怎么展开是不够的,你最好还要记住常见的几个函数的展开,这里只给出结果(我相信你不需要过程2333)
(好展开的)三角函数们:
$\sin(x)=\frac{x}{1!}-\frac{x^3}{3!}+\frac{x^5}{5!}......$
$\cos(x)=\frac{x^0}{0!}-\frac{x^2}{2!}+\frac{x^4}{4!}......$
$\arcsin(x)=x+\frac{1}{2}*\frac{x^3}{3}+\frac{1*3}{2*4}*\frac{x^5}{5}......$
自然对数
$\ln(x+1)=x-\frac{1}{2}x^2+\frac{1}{3}x^3......$
自然指数
$e^x=1+\frac{1}{1!}x+\frac{1}{2!}x^2$
二项式定理
$(x+1)^k=1+\frac{k}{1!}x+\frac{k(k-1)}{2!}x^2......$
几何级数
$\frac{1}{1-x}=1+x+x^2......$
7.生成函数
将数列问题转化为函数问题的一种工具,我们称$f(x)=a_0x^0+a_1x^1+a_2x^2......$为数列$a$的生成函数,可以在生成函数上进行一些操作之后把它还原成数列
不过它更常用的操作是解决组合的问题,比如我们有重量为1g,2g和5g的砝码各3个,然后问你能凑出哪些重量,每种又有多少种方案,可以这样用生成函数解
$f(1g)=(1+x^1+x^2+x^3)$ $f(2g)=(1+x^2+x^4+x^6)$ $f(5g)=(1+x^5+x^{10}+x^{15})$
然后乘起来,各项系数就是方案数,指数就是重量,然后找到了一个板子(From @小飞_Xiaofei )
用$val[i]$表示第$i$个物品的价值或者重量,$n1[i]$表示第$i$种物品最少要取多少个。$n2[i]$表示第$i$种物品最多要取多少个
1 int cntv,maxw;//物品种类数,最大限制 2 int a[MAX],b[MAX]; a[0]=1; 3 for(int i=1;i<=cntv;i++) 4 { 5 memset(b,0,sizeof b); 6 for(int j=n1[i];j<=n2[i]&&j*v[i]<=maxw;j++) 7 for(int k=0;k+j*v[i]<=maxv;k++) 8 b[k+j*v[i]]+=a[k]; 9 memcpy(a,b,sizeof(b)); 10 }
如果就是要求数列怎么办呢?
— —解方程
8.差分
一个等差数列上的$k$次函数差分$k+1$次后全是零
9.群论入门
在i207M(orz 的帮助下花了半个晚自习终于搞懂了一些基本定义=。=
//跑一会题↓
然后我必须要吐槽一下:
你在网上找到的群论知识可能都是这种画风的:
“在数学中,群表示一个拥有满足封闭性、结合律、有单位元、有逆元的二元运算的代数结构,包括阿贝尔群、同态和共轭类。”(百度百科-群(数学概念))
这种画风的:
“n元对称群的任意一个子群,都叫做一个n元置换群,简称置换群。置换群是最早研究的一类群,是十分重要的群,每个有限的抽象群都与一个置换群同构......”(百度百科-置换群)
甚至是这种画风的:
“设G是[1,n]上的一个置换群。G是Sn的一个子群. k∈[1,n],G中使k元素保持不变的置换全体,称为k不动置换类,记做Zk。设G={a1,a2,…ag}是目标集[1,n]上的置换群。每个置换都写成不相交循环的乘积......”(百度百科-Burnside引理)
(像菜鸡博主一样)零基础的话谁看得懂啊=。=!
//跑回来了↑
我们通俗地解释一下一些群论的简单概念
群:如果存在在某些运算下的一个集合,这个集合的元素在这些运算下满足封闭性(运算出来的东西还在集合里)和结合律(设运算为@,则(a@b)@c=a@(b@c)),有单位元(与其他元素$o$运算的结果仍是$o$的元素)和逆元(与其他元素$o$运算相当于取消了另一个元素$b$得到$o$的运算的元素),那么就称这些运算是建立于这个集合上的一个群
置换:一个集合到自己的一个双射,所谓双射就是每个元素的映射唯一且每个元素都有自己的映射
置换群:一类置换组成的群,请将置换当做一种运算配合上面两个定义食用,比如说向右循环移位是一个置换群,它由向右循环移1位,向右循环移2位,向右循环移3位......组成
等价类(在群论中):建立在某种置换群基础上的定义,在这种置换群下可以经过各种组合起来的置换互相转化成的状态属于一个等价类。举个例子:
1 2 3 和 3 1 2 在置换(1->2,2->3,3->1)下属于一个等价类,前者可以经过一次这个置换变成后者,后者可以经过两次这个置换变成前者
不动点(在群论中):建立在某种置换群基础上的定义,在这种置换群下无论如何运算都不变化的状态称作一个不动点。举个例子
2 1 2在置换(1->3,2->2,3->1)下是一个不动点
循环(在群论中):把一个置换看做一张有向图,那么循环就是图中的环。举个例子
置换(1->3,2->1,3->2,4->5,5->4)中有两个循环,分别是(1 3 2)和(4 5)
循环分解就是把一个置换分解成若干个循环
好了现在应用这些定义解释一下Burnside引理和Polya定理
Burnside引理:令置换群$G$作用于有限集合$S$上,则$S$中的等价类数目等于每个置换子群下不动点数目的和的平均值,即对置换群的大小作除法
如果你喜欢看公式的话:
$ans=\frac{\sum_{g∈G}S(g)}{|G|}$
常见的用法:在旋转置换下,如果知道循环节长度为i的答案$f(i)$,那么总方案即$\frac{1}{n}\sum_{d|n}φ(d)f(\frac{n}{d})$
划重点: 置换群,有限集合
还是举例子
长度为3,元素分别为1 2 3的所有排列组成一个有限集合,现在我们令数组的向右循环移位(1位,2位,3位,再多就循环了和之前一样了)这个置换群作用于它,那么等价类的数目是
$\frac{\sum_{g∈G}S(g)}{|G|}=\frac{6}{3}=2$
解释:所有的6种排列在循环右移3位下都是不动点,而置换群的大小是3,所以总共有2个等价类(分别是1 2 3和1 3 2)
Polya定理:令置换群$G$作用于有限集合$S$上,用$k$种颜色为$S$的元素染色,则$S$中的等价类数目等于每个置换子群下$k$的不动点数目次幂的和的平均值
它是Burnside引理的一种特殊应用,理解了Burnside引理就能理解
10.牛顿迭代
找函数零点
若函数$f$二阶可导,那么函数必存在一个区域,从这个区域开始牛顿迭代必定能够收敛,具体来说牛顿迭代是这样的
设$f$的导数为$d$,那么从开始的$x_0$开始每次对$x_{last}-\frac{f(x_{last})}{d(x_{last})}$迭代即可,注意如果要求零点的范围要控制范围
在图形上来看更加直观:就是你每次在上一次位置的函数图像的切线的零点开始下一次迭代
1 double Iterate(double x) 2 { 3 for(int i=1;i<=30;i++) 4 { 5 double y=Ask(f,x,n); 6 if(fabs(y)<=eps) return x; 7 x-=y/Ask(d,x,nm),x=max(x,ll),x=min(x,rr); 8 } 9 return inf; 10 }
11.积分瞎学
概念普及(极为不严谨预警):
函数中的一个永远在变化的变量$x$,其值不断逼近一个已知值$A$但永远不等于$A$。这种趋势叫做极限(?),$A$叫做极限值,称$x$趋近于$A$
收敛(这个粘的百度百科):对于函数$f(x)$,若对于任意实数$b>0$,存在$c>0$,对任意$x1,x2$满足$0<|x1-x0|<c,0<|x2-x0|<c$,有$|f(x1)-f(x2)|<b$,则称$f(x)$于$x0$收敛
洛必达法则:简单来说就是两个都趋近于零或者无穷的函数,若它们在限定区域内都可导,则它们的比值等于它们导数的比值
12.二次剩余
可以理解为模意义下的平方根,即称满足$x^2 \equiv n \mod p$的x是n在模p意义下的二次剩余
求法:先检查 $n^{\frac{p-1}{2}}$ 是否$\equiv 1 \mod p$,如果是则n在模p意义下有二次剩余(如果是-1说明没有)。之后随机一个x直到 $y=x^2-n$ 在模p意义下没有二次剩余,那么答案即$(x+\sqrt y)^{\frac{n+1}{2}}$
根号是什么鬼?
定义一个类似复数的乘法即可
可以看i207M的