数论总结
Posted cptbtptpbcptbtptp
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了数论总结相关的知识,希望对你有一定的参考价值。
前言:刷了几天的数论题目,总结一下
1、拓展欧几里得:求解不定方程ax+by=c【当c%gcd(a,b)≠0时,方程无解】
1 void exgcd(ll a,ll b,ll &d,ll &x,ll &y) 2 3 if(!b) x=1,y=0,d=a; 4 else exgcd(b,a%b,d,x,y);int t=x;x=y;y=t-a/b*y; 5
2、欧拉函数:φ (x)表示不大于x的数中与x互质的数的个数
1 for(int i=2;i<=n-1;i++) 2 3 if(!b[i]) 4 5 prime[++cnt]=i; 6 phi[i]=i-1; 7 8 for(int j=1;j<=cnt&&i*prime[j]<=n-1;j++) 9 10 b[i*prime[j]]=1; 11 if(i%prime[j]==0) 12 13 phi[i*prime[j]]=phi[i]*prime[j]; 14 break; 15 16 phi[i*prime[j]]=phi[i]*(prime[j]-1); 17 18
题目:仪仗队
3、快速幂:快速求ab
1 ll qpow(ll b) 2 3 ll a=10,ret=1; 4 while(b) 5 6 if(b%2==1) ret=ret*a%n; 7 a=a*a%n; 8 b=b>>1; 9 10 return ret; 11
题目:转圈游戏 Raising Modulo Numbers
4、矩阵运算
题目:Fibonacci
该题代码:
1 #include<algorithm> 2 #include<iostream> 3 #include<cstring> 4 #include<vector> 5 using namespace std; 6 typedef long long ll; 7 const int MOD=10000; 8 typedef vector<ll> vec; 9 typedef vector<vec> matrix; 10 matrix mul(matrix &a,matrix &b) 11 12 matrix c(a.size(),vec(b[0].size())); 13 for(int i=0;i<2;++i) 14 15 for(int j=0;j<2;++j) 16 17 for(int k=0;k<2;++k) 18 19 c[i][j]+=a[i][k]*b[k][j]; 20 c[i][j]%=MOD; 21 22 23 24 return c; 25 26 matrix qpow(matrix a,ll n) 27 28 matrix res(a.size(),vec(a.size())); 29 for(int i=0;i<a.size();++i) 30 res[i][i]=1; 31 while(n) 32 33 if(n%2==1) res=mul(res,a); 34 a=mul(a,a); 35 n=n>>1; 36 37 return res; 38 39 ll solve(ll n) 40 41 matrix a(2,vec(2)); 42 a[0][0]=1; 43 a[0][1]=1; 44 a[1][0]=1; 45 a[1][1]=0; 46 a=qpow(a,n); 47 return a[0][1]; 48 49 int main() 50 51 ll n; 52 cin>>n; 53 while(n!=-1) 54 55 cout<<solve(n)<<endl; 56 cin>>n; 57 58 return 0; 59
5、Lucas定理:快速求C(m,m+n)%p【p为质数】
题目:卢卡斯定理
1 #include<iostream> 2 #include<algorithm> 3 using namespace std; 4 const int N=100005; 5 typedef long long ll; 6 ll t,n,m,p,a[N]; 7 inline ll qpow(ll y,ll z,ll p) 8 9 y%=p; 10 ll ans=1; 11 for(int i=z;i;i>>=1,y=y*y%p)if(i&1)ans=ans*y%p; 12 return ans; 13 14 inline ll C(ll n,ll m) 15 16 if(m>n)return 0; 17 return ((a[n]*qpow(a[m],p-2,p))%p*qpow(a[n-m],p-2,p)%p); 18 19 inline ll Lucas(int m,int n) 20 21 if(n==0) 22 return 1; 23 return Lucas(m/p,n/p)%p*C(m%p,n%p); 24 25 int main() 26 27 p=5000011; 28 cin>>m>>n; 29 a[0]=1; 30 for(int i=1;i<=p;++i) 31 a[i]=(a[i-1]*i)%p; 32 cout<<Lucas(m+n,n)%p<<endl; 33 return 0; 34
6、素数筛
1 int main() 2 3 int n, cnt = 0; 4 int prime[100001]; 5 bool vis[100001]; 6 scanf("%d", &n); 7 memset(vis, false, sizeof(vis)); 8 memset(prime, 0, sizeof(prime)); 9 for(int i = 2; i <= n; i++) 10 11 if(!vis[i]) 12 prime[cnt++] = i; 13 for(int j = 0; j<cnt && i*prime[j]<=n; j++) 14 15 vis[i*prime[j]] = true; 16 if(i % prime[j] == 0) break; 17 18 19 printf("%d\n", cnt); 20
7、*博弈论
①巴什博奕:一堆n个物品,两个人从轮流中取出(1~m)个;最后取光者胜
1 int BashGame(int n,int m) 2 3 if(n%(m+1)) return 0; 4 return 1; 5
②Nim博弈:n堆物品,两人轮流取,每次取某堆中不少于1个,最后取完者胜
1 int NimGame(int n) 2 3 int flag=0; 4 for(int i=0;i<n;i++) 5 flag^=f[i]; 6 if(flag)return 1; 7 return 0; 8
③威佐夫博弈:两堆(ak,bk)(ak<=bk)个物品,两人轮流取,每次从一堆中取k个或者从2堆中同时取k个,最后面对(0,0)局面的输
1 int WGame(int a,int b) 2 3 a=min(a,b); 4 b=max(a,b); 5 int k=b-a; 6 double path=(sqrt(5)+1)/2; 7 if(a==floor(path*k) return 1; 8 return 0; 9
④斐波那契博弈:一堆石子有n个,两人轮流取,先取者第1次可以取任意多个,但不能全部取完,以后每次取的石子数不能超过上次取子数的2倍。取完者胜
1 int FibonacciGame(int n) 2 3 if(n==1) return 1; 4 int f[1e5]; 5 f[0]=f[1]=1; 6 for(int i=2;f[i-1]<n;i++) 7 8 f[i]=f[i-1]+f[i-2]; 9 if(f[i]==n) return 1; 10 11 return 0; 12
8、球盒问题(组合数学):见 → 来自大佬的博客
以上是关于数论总结的主要内容,如果未能解决你的问题,请参考以下文章