常用数论模板
Posted hzoi-lyl
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了常用数论模板相关的知识,希望对你有一定的参考价值。
1 //----------------------------------------------------------------------------- 2 /*快速幂*/ 3 inline int qpow(re int x,re int y,re int res=1){ 4 for(;y;y>>=1,x=x*x%mod) if(y&1) res=res*x%mod; return res; 5 } 6 //----------------------------------------------------------------------------- 7 /*gcd*/ 8 //gcd 9 inline int gcd(re int x,re int y){return !y?x:gcd(y,x%y);} 10 //lcm 11 inline int lcm(re int x,re int y){return x*y/gcd(x,y);} 12 //----------------------------------------------------------------------------- 13 /*exgcd*/ 14 inline int exgcd(re int a,re int b,re int &x,re int &y){ 15 re int ret,tmp;if(!b){x=1,y=0; return a;} 16 ret=exgcd(b,a%b,x,y),tmp=x,x=y,y=tmp-a/b*y; 17 return ret; 18 } 19 //----------------------------------------------------------------------------- 20 /*分解质因数*/ 21 for(re int i=1;prime[i]*prime[i]<=x;++i){ 22 while(x%prime[i]==0) 23 x/=prime[i],p[++p[0]]=prime[i]; 24 } 25 if(x>1) p[++p[0]]=x; 26 //----------------------------------------------------------------------------- 27 /*线性筛*/ 28 //素数 29 for(re int i=2;i<=n;++i){ 30 if(!vis[i]) prime[++cnt]=i,vis[i]=1; 31 for(re int j=1;j<=cnt&&i*prime[j]<=n;++j){ 32 vis[i*prime[j]]=1; 33 if(i%prime[j]==0) break; 34 } 35 } 36 //约数个数和 37 d[1]=1; 38 for(re int i=2;i<=n;++i){ 39 if(!vis[i]) prime[++cnt]=i,d[i]=2,c[i]=1; 40 for(re int j=1;j<=cnt&&i*prime[j]<=n;++j){ 41 vis[i*prime[j]]=1; 42 if(i%prime[j]==0){ 43 c[i*prime[j]]=c[i]+1; 44 d[i*prime[j]]=d[i]/(c[i]+1)*(c[i]+2); 45 break; 46 } 47 d[i*prime[j]]=d[i]*2; 48 c[i*prime[j]]=1; 49 } 50 } 51 //约数和 52 s[1]=1; 53 for(re int i=2;i<=n;++i){ 54 if(!vis[i]) prime[++cnt]=i,s[i]=i+1,c[i]=i+1; 55 for(re int j=1;j<=cnt&&i*prime[j]<=n;++j){ 56 vis[i*prime[j]]=1; 57 if(i%prime[j]==0){ 58 c[i*prime[j]]=c[i]*prime[j]+1; 59 s[i*prime[j]]=s[i]/c[i]*c[i*prime[j]]; 60 break; 61 } 62 d[i*prime[j]]=d[i]*(prime[j]+1); 63 c[i*prime[j]]=prime[j]+1; 64 } 65 } 66 //莫比乌斯函数 67 mu[1]=1; 68 for(re int i=2;i<=n;++i){ 69 if(!vis[i]) prime[++cnt]=i,mu[i]=-1; 70 for(re int j=1;j<=cnt&&i*prime[j]<=n;++j){ 71 vis[i*prime[j]]=1; 72 if(i%prime[j]==0) break; 73 mu[i*prime[j]]=-mu[i] 74 } 75 } 76 //欧拉函数 77 phi[1]=1; 78 for(re int i=2;i<=n;++i){ 79 if(!vis[i]) prime[++cnt]=i,phi[i]=i-1; 80 for(re int j=1;j<=cnt&&i*prime[j]<=n;++j){ 81 vis[i*prime[j]]=1; 82 if(i%prime[j]==0){ 83 phi[i*prime[j]]=phi[i]*prime[j]; 84 break; 85 } 86 phi[i*prime[j]]=phi[i]*phi[prime[j]]; 87 } 88 } 89 //求单个欧拉函数 90 inline int phi(re int x){ 91 re int dat=sqrt(x),res=x; 92 for(re int i=2;i<=dat;i++) 93 if(x%i==0){ 94 res=res-res/i; 95 while(x%i==0) x/=i; 96 } 97 if(x!=1) res=res-res/x; 98 return res; 99 } 100 //----------------------------------------------------------------------------- 101 /*BSGS*/ 102 #include<tr1/unordered_map>//底层为hash的map,可以减少map带来的log级别的复杂度 103 tr1::unordered_map<int,int> mp; 104 inline int qpow(re int x,re int y,re int res=1){ 105 for(;y;y>>=1,x=x*x%p) if(y&1) res=res*x%p; return res; 106 } 107 scanf("%d%d%d",&p,&a,&b); 108 if(a%p==0) 109 printf("no solution ");return 0; 110 m=ceil(sqrt(p)),flag=0; 111 now=b%p;mp[now]=0;//b*a^j 当j==0时 112 for(re int i=1;i<=m;++i) 113 now=(now*a)%p,mp[now]=i; 114 dat=qpow(a,m);now=1; 115 for(re int i=1;i<=m;++i){//枚举 (a^m)^i 116 now=(now*dat)%p; 117 if(mp[now]){ 118 flag=1; 119 ans=i*m-mp[now]; 120 printf("%lld ",(ans%p+p)%p); 121 break; 122 } 123 } 124 if(!flag) printf("no solution "); 125 //----------------------------------------------------------------------------- 126 /*CRT*/ 127 //n个方程:x=a[i](mod m[i]) (0<=i<n) 128 inline void exgcd(int a,int b,int &x,int &y,int &d){ 129 if(!b){x=1,y=0,d=a;} 130 else exgcd(b,a%b,y,x,d),y-=x*(a/b); 131 } 132 inline int inv(re int t,re int p){ 133 re int dat,x,y; 134 exgcd(t,p,x,y,dat); 135 return dat==1?(x%p+p)%p:-1; 136 } 137 inline int China(re int x,re int *a,re int *b){ 138 re int dat=1,res=0; 139 for(re int i=0;i<x;++i) dat*=b[i]; 140 for(re int i=0;i<x;++i){ 141 re int val=dat/b[i]; 142 res=(res+val*inv(val,b[i])*a[i])%dat; 143 } 144 return (res+dat)%dat; 145 } 146 //----------------------------------------------------------------------------- 147 /*排列组合*/ 148 //阶乘 149 fac[0]=1; 150 for(re int i=1;i<=n;++i) 151 fac[i]=fac[i-1]*i%mod; 152 //逆元(线性) 153 inv[0]=inv[1]=1; 154 for(re int i=2;i<=n;++i) 155 inv[i]=inv[mod%i]*(mod-mod/i)%mod; 156 //组合数 157 inline int C(re int x,re int y){ 158 if(x<y) return 0;if(x==y) return 1; 159 return fac[x]*inv[y]%mod*inv[x-y]%mod; 160 } 161 //排列数 162 inline int A(re int x,re int y){ 163 if(x<y) return 0;if(x==y) return fac[x]; 164 return fac[x]*inv[x-y]%mod; 165 } 166 //卡特兰数 167 inline int katelan(re int x){ 168 return C(x<<1,x)*inv[x+1]%mod; 169 } 170 //----------------------------------------------------------------------------- 171 /*lucas*/ 172 int lucas(re int x,re int y){ 173 if(!y) return 1; 174 return C(x%mod,y%mod)*lucas(x/mod,y/mod)%mod; 175 } 176 //----------------------------------------------------------------------------- 177 /*高斯消元*/ 178 inline void work(){ 179 for(re int i=1;i<=n;++i){ 180 re int now=i; 181 for(re int j=i+1;j<=n;++j) 182 if(fabs(a[j][i]>a[now][i])) now=j; 183 if(now!=i){ 184 for(re int j=i;j<=n+1;++j) 185 swap(a[i][j],a[now][j]); 186 } 187 if(a[i][i]=0){flag=1; return;} 188 for(re int j=i+1;j<=n+1;++j) 189 a[i][j]=a[i][j]/a[i][i]; 190 a[i][i]=1; 191 for(re int j=i+1;j<=n;++j){ 192 for(re int k=i+1;k<=n+1;++k) 193 a[j][k]-=a[i][k]*a[j][i]; 194 a[j][i]=0; 195 } 196 } 197 for(re int i=n;i;--i) 198 for(re int j=i+1;j<=n;++j) 199 a[i][n+1]-=a[i][j]*a[j][n+1]; 200 } 201 work();if(flag)->无解 202 for(re int i=1;i<=n;i++) 203 printf("%.2lf ",a[i][n+1]); 204 //-----------------------------------------------------------------------------
以上是关于常用数论模板的主要内容,如果未能解决你的问题,请参考以下文章
[AndroidStudio]_[初级]_[配置自动完成的代码片段]