NOIP数学相关模板整理
$O(n)$递推求逆元
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 using namespace std; 5 typedef long long ll; 6 int inv[3000010]; 7 int main(){ 8 int n,p; 9 scanf("%d%d",&n,&p); 10 inv[1]=1; 11 printf("1\n"); 12 for(int i=2;i<=n;i++){ 13 inv[i]=(ll)(p-p/i)*inv[p%i]%p; 14 printf("%d\n",inv[i]); 15 } 16 return 0; 17 }
exgcd求逆元
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 using namespace std; 5 void exgcd(int a,int b,int &x,int &y){ 6 if(!b){ 7 x=1; 8 y=0; 9 return; 10 } 11 exgcd(b,a%b,x,y); 12 int tmp=x; 13 x=y; 14 y=tmp-a/b*y; 15 } 16 int main(){ 17 int a,b; 18 scanf("%d%d",&a,&b); 19 int x,y; 20 exgcd(a,b,x,y); 21 x=(x%b+b)%b; 22 printf("%d\n",x); 23 return 0; 24 }
模数为质数时,用费马小定理求逆元
1 #include<cstdio> 2 typedef long long ll; 3 const int mod=1e9+7; 4 ll ksm(ll x,ll y){ 5 ll ret=1; 6 while(y){ 7 if(y&1) ret=ret*x%mod; 8 x=x*x%mod; 9 y>>=1; 10 } 11 return ret; 12 } 13 int main(){ 14 ll a; 15 scanf("%lld",&a); 16 printf("%lld",ksm(a,mod-2)); 17 return 0; 18 }
$O(n)$求$1!$到$N!$的逆元
$1/i!=(i+1)/(i+1)!$
实现时先求出$f[n]$再反向递推
1 f[i]=(ll)(i+1)*f[i+1]%mod
中国剩余定理
贴一篇别人的:http://www.cnblogs.com/MashiroSky/p/5918158.html
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 using namespace std; 5 typedef long long ll; 6 int N,A[15],B[15]; 7 void Exgcd(ll a,ll b,ll &x,ll &y){ 8 if(!b){ 9 x=1; 10 y=0; 11 return; 12 } 13 Exgcd(b,a%b,x,y); 14 ll tmp=x; 15 x=y; 16 y=tmp-a/b*y; 17 } 18 ll Chinese_Remainder_Theorem(){ 19 ll M=1; 20 for(int i=1;i<=N;i++) M*=A[i]; 21 ll ret=0,x,y; 22 for(int i=1;i<=N;i++){ 23 ll tmp=M/A[i]; 24 Exgcd(tmp,A[i],x,y); 25 ret=(ret+tmp*x*B[i])%M; 26 } 27 return (ret+M)%M; 28 } 29 int main(){ 30 return 0; 31 }
Lucas定理
$C(N,M)\% P = C(N\% P,M\% P) * C(N/P,M/P)\% P$
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 using namespace std; 5 typedef long long ll; 6 int N,M,P; 7 int inv[100010],fac[100010]; 8 int C(int x,int y){ 9 if(x<y) return 0; 10 return (ll)fac[x]*inv[fac[y]]%P*inv[fac[x-y]]%P; 11 } 12 int Lucas(){ 13 if(N<M) return 0; 14 ll ret=1; 15 while(M){ 16 ret=ret*C(N%P,M%P)%P; 17 N/=P; 18 M/=P; 19 } 20 return ret; 21 } 22 int main(){ 23 int Test; 24 scanf("%d",&Test); 25 while(Test--){ 26 scanf("%d%d%d",&N,&M,&P); 27 swap(N,M); 28 N+=M; 29 inv[1]=1;for(int i=2;i<P;i++) inv[i]=(ll)(P-P/i)*inv[P%i]%P; 30 fac[0]=1;for(int i=1;i<=N;i++) fac[i]=(ll)fac[i-1]*i%P; 31 printf("%d\n",Lucas()); 32 } 33 return 0; 34 }
高斯消元
最后回代求解的时候,若发现某一项元系数为零,且式子右边常数为零,则有无数多个解,若常数不为零,则无解。
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 #include<cmath> 5 using namespace std; 6 int inline readint(){ 7 int Num=0,Flag=1;char ch; 8 while((ch=getchar())<'0'||ch>'9') if(ch=='-') break; 9 if(ch=='-') Flag=-1; else Num=ch-'0'; 10 while((ch=getchar())>='0'&&ch<='9') Num=Num*10+ch-'0'; 11 return Num*Flag; 12 } 13 int N; 14 double A[110][110]; 15 bool Gauss(){ 16 int t; 17 for(int i=1;i<=N;i++){ 18 t=i; 19 for(int j=i+1;j<=N;j++) 20 if(fabs(A[j][i])>fabs(A[t][i])) 21 t=j; 22 if(t!=i) 23 for(int j=i;j<=N+1;j++) 24 swap(A[t][j],A[i][j]); 25 for(int j=i+1;j<=N;j++){ 26 double r=A[j][i]/A[i][i]; 27 for(int k=i;k<=N+1;k++) 28 A[j][k]-=A[i][k]*r; 29 } 30 } 31 for(int i=N;i>=1;i--){ 32 for(int j=i+1;j<=N;j++) 33 A[i][N+1]-=A[i][j]*A[j][N+1]; 34 if(A[i][i]==0&&A[i][N+1]==0) return false; 35 A[i][N+1]/=A[i][i]; 36 } 37 return true; 38 } 39 int main(){ 40 N=readint(); 41 for(int i=1;i<=N;i++) 42 for(int j=1;j<=N+1;j++) 43 A[i][j]=readint(); 44 if(!Gauss()){ 45 puts("No Solution"); 46 return 0; 47 } 48 for(int i=1;i<=N;i++) printf("%.2lf\n",A[i][N+1]); 49 return 0; 50 }