常用数论模板

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 //-----------------------------------------------------------------------------

 

以上是关于常用数论模板的主要内容,如果未能解决你的问题,请参考以下文章

C#常用代码片段备忘

nodejs常用代码片段

PAT 数列的片段和简单数论

[AndroidStudio]_[初级]_[配置自动完成的代码片段]

[AndroidStudio]_[初级]_[配置自动完成的代码片段]

数论模板总结 -- 未完待续