数论学习
来源:互联网 发布:手机一键还原软件 编辑:程序博客网 时间:2024/05/19 09:39
1⃣️扩展欧几里得算法
sgu 141 扩展欧几里德+枚举大法,不过sgu好像崩了。。。。
poj 2891
合并模方程式
#include <cstdio>#include <iostream>#include <algorithm>#include <cstring>#include <cmath>#include <queue>#include <vector>using namespace std;#define N 100010typedef long long ll;ll K;ll a[N],r[N];inline ll read(){ ll x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch<='9'&&ch>='0'){x=x*10+ch-'0';ch=getchar();} return x*f;}void Exgcd(ll a,ll b,ll &x,ll &y,ll &d){ if(b==0) { d=a;x=1;y=0; return; } Exgcd(b,a%b,y,x,d); y-=a/b*x;}ll work(){ ll Last_a=a[1],Last_r=r[1],x,y,d; for(int i=2;i<=K;i++) { Exgcd(Last_a,a[i],x,y,d); if((r[i]-Last_r)%d!=0) return -1; ll tmp=a[i]/d; x=((r[i]-Last_r)/d*x)%tmp; Last_r+=x*Last_a; Last_a=Last_a/d*a[i]; Last_r%=Last_a; } return Last_r>0?Last_r:Last_r+Last_a;}int main(){ while(scanf("%lld",&K)!=EOF) { for(ll i=1;i<=K;i++) { a[i]=read();r[i]=read(); } printf("%lld\n",work()); } return 0;}
2⃣️Miller-Rabbin 素数检测法
1.费马小定理
2.二次探测定理
#include <cstdio>#include <iostream>#include <algorithm>#include <cstring>#include <cmath>#include <queue>#include <vector>using namespace std;typedef long long ll;const int S=3;int K,Ans;ll A[4]={0,2,7,61}; //黑科技一波inline ll read(){ int x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch<='9'&&ch>='0'){x=x*10+ch-'0';ch=getchar();} return x*f;}ll Quick_mul(ll a,ll b,ll n){ ll base=a,r=0; while(b) { if(b&1) r=(r+base)%n; base=(base+base)%n; b>>=1; } return r;}ll Quick_pow(ll a,ll exp,ll n){ ll base=a,r=1; while(exp) { if(exp&1) r=r*base%n; base=base*base%n; exp>>=1; } return r;}bool Miller_Rabbin(ll n){ if(n==2)return true; int t=0; ll a,x,y,u=n-1; while(!(u&1)) { t++;u>>=1; } for(int i=1;i<=S;i++) { a=A[i]; x=Quick_pow(a,u,n); for(int j=1;j<=t;j++) { y=Quick_mul(x,x,n); if(y==1&&x!=1&&x!=n-1) return false; x=y; } if(x!=1) return false; } return true;}int main(){ while(scanf("%d",&K)!=EOF) { Ans=0; for(int i=1;i<=K;i++) { ll n=read(); if(Miller_Rabbin(n)) Ans++; } printf("%d\n",Ans); } return 0;}
3⃣️.快速求逆元
4⃣️卢卡斯定理 ---组合数取模
Lucas(n,m,p)=c(n%p,m%p)*Lucas(n/p,m/p,p)
1.hdu 3037 Saving Beans
#include <cstdio>#include <iostream>#include <algorithm>#include <cstring>#include <cmath>#include <queue>#include <vector>using namespace std;#define N 100010typedef long long ll;int T;ll n,m,p;ll pre[N],S_pre[N];ll Quick_mul(ll a,ll b){ ll base=a,r=0; while(b) { if(b&1) r=(r+base)%p; base=(base+base)%p; b>>=1; } return r;}ll Quick_pow(ll a,ll exp){ ll base=a,r=1; while(exp) { if(exp&1) r=Quick_mul(r,base); base=Quick_mul(base,base); exp>>=1; } return r;}void Prepare(){ pre[0]=1; for(int i=1;i<=p;i++) pre[i]=pre[i-1]*i%p; S_pre[p-1]=Quick_pow(pre[p-1],p-2); for(int i=(int)p-2;i>=1;i--) S_pre[i]=S_pre[i+1]*(i+1)%p; S_pre[0]=1;}int main(){ scanf("%d",&T); while(T--) { scanf("%lld%lld%lld",&n,&m,&p); n+=m; Prepare(); ll Ans=1; while(n||m) { ll t1=n%p,t2=m%p; if(t1<t2) { Ans=0;break; } ll tmp=((pre[t1]*S_pre[t1-t2])%p*S_pre[t2])%p; Ans=Ans*tmp%p; n/=p;m/=p; } printf("%lld\n",Ans); } return 0;}
5⃣️.中国剩余定理
网上看了好多都是在乱扯。。。强行把欧几里德题解说成中国剩余定理 如上poj 2891
1.hdu 1370 Biorhythms
#include <cstdio>#include <iostream>#include <algorithm>#include <cstring>#include <cmath>#include <queue>#include <vector>using namespace std;#define N 10typedef long long ll;ll A[N],B[N],C[N];inline ll read(){ ll x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch<='9'&&ch>='0'){x=x*10+ch-'0';ch=getchar();} return x*f;}void Exgcd(ll a,ll b,ll &x,ll &y,ll &d){ if(b==0) { d=a;x=1;y=0; return; } Exgcd(b,a%b,y,x,d); y-=a/b*x;}int main(){ ll Zy=read(); ll Lim_min,x,y,d; ll Mul=23*28*33; Exgcd(Mul/23,23,x,y,d);B[1]=x;C[1]=23; Exgcd(Mul/28,28,x,y,d);B[2]=x;C[2]=28; Exgcd(Mul/33,33,x,y,d);B[3]=x;C[3]=33; int Case=0; while(scanf("%lld%lld%lld%lld",&A[1],&A[2],&A[3],&Lim_min)) { if(A[1]==-1&&A[2]==-1&&A[3]==-1&&Lim_min==-1) break; ll Ans=0; for(int i=1;i<=3;i++) { Ans=(Ans+Mul/C[i]*B[i]*A[i])%Mul; } if(Ans<=Lim_min) { ll qwer=(Lim_min-Ans)/Mul+1; Ans+=qwer*Mul; } printf("Case %d: the next triple peak occurs in %lld days.\n",++Case,Ans-Lim_min); } return 0;}
6⃣️欧拉函数与莫比乌斯函数
1.hdu 2824 (线性筛求欧拉函数)
#include <cstdio>#include <iostream>#include <algorithm>#include <cstring>#include <cmath>#include <queue>#include <vector>using namespace std;#define N 3000010int a,b,tot;int phi[N],Prime[N/3];bool flag[N];void Prepare(){ for(int i=2;i<=3000000;i++) { if(!flag[i]) { Prime[++tot]=i; phi[i]=i-1; } for(int j=1;(long long)Prime[j]*i<=3000000;j++) { flag[i*Prime[j]]=1; if(i%Prime[j]==0) { phi[i*Prime[j]]=phi[i]*Prime[j]; break; } else phi[i*Prime[j]]=phi[i]*(Prime[j]-1); } }}int main(){ Prepare(); while(scanf("%d%d",&a,&b)!=EOF) { long long Ans=0; for(int i=a;i<=b;i++) Ans+=phi[i]; printf("%lld\n",Ans); } return 0;}
2.求 ∑gcd(i,j) 1≤i≤n , 1≤j≤m
Orz KZF
其过程就是不断替换求和公式的变量得到新的求和公式(瞎bb的)
#include <cstdio>#include <iostream>#include <algorithm>#include <cstring>#include <cmath>#include <queue>#include <vector>using namespace std;#define N 100010int n,m,tot;int Prime[N],phi[N];bool flag[N];void Prepare(){ phi[1]=1; for(int i=2;i<=100000;i++) { if(!flag[i]) { Prime[++tot]=i; phi[i]=i-1; } for(int j=1;(long long)Prime[j]*i<=100000;j++) { flag[i*Prime[j]]=true; if(i%Prime[j]==0) { phi[i*Prime[j]]=phi[i]*Prime[j]; break; } else phi[i*Prime[j]]=phi[i]*(Prime[j]-1); } }}int main(){ Prepare(); int a,b;scanf("%d%d",&a,&b); n=min(a,b);m=max(a,b); long long Ans=0; for(int i=1;i<=n;i++) { Ans+=(long long)(n/i)*(m/i)*phi[i]; } cout<<Ans<<endl; return 0;}
那么如果n是10^9数量级的呢?
让我们继续orz
复杂度s
是O(n^0.67)
3.poj 2480 (被网上坑了。。。看了好久。。暴力不就行了么,推个毛公式啊)
#include <cstdio>#include <iostream>#include <algorithm>#include <cstring>#include <cmath>#include <queue>#include <vector>using namespace std;#define N 1000010int n,tot;int Prime[N];bool flag[N];void Prepare(){ for(int i=2;i<=1000000;i++) { if(!flag[i]) { Prime[++tot]=i; } for(int j=1;(long long)Prime[j]*i<=1000000;j++) { flag[i*Prime[j]]=true; if(i%Prime[j]==0) break; } }}int Get_phi(int k){ if(k==1)return 1; int num=k; for(int i=1;i<=tot;i++) { if(k%Prime[i]==0) { num=num/Prime[i]*(Prime[i]-1); while(k%Prime[i]==0) k/=Prime[i]; if(k==1) break; } } if(k!=1) num=num/k*(k-1); return num;}int main(){ Prepare(); while(scanf("%d",&n)!=EOF) { long long Ans=0; for(int i=1;i<=sqrt((double)n);i++) { if(n%i==0) { Ans+=(long long)i*Get_phi(n/i); if(i!=(n/i)) { int t=n/i; Ans+=(long long)t*Get_phi(i); } } } printf("%lld\n",Ans); } return 0;}
4.NYOJ 1066 CO—PRIME
莫比乌斯反演
此题中,设F(d)表示n个数中gcd为d的倍数的数有多少对,f(d)表示n个数中gcd恰好为d的数有多少对,
则F(d)=∑f(n) (n % d == 0)
f(d)=∑mu[n / d] * F(n) (n %d == 0)
---------> f(1)=∑mu[n] * F(n)
.......(摘抄From http://blog.csdn.net/lyhvoyage/article/details/38455415)
#include <cstdio>#include <iostream>#include <algorithm>#include <cstring>#include <cmath>#include <queue>#include <vector>using namespace std;#define N 100010int n,tot,Max;int A[N],Prime[N],mu[N],num[N],cnt[N];bool flag[N];inline int read(){ int x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch<='9'&&ch>='0'){x=x*10+ch-'0';ch=getchar();} return x*f;}void Prepare(){ mu[1]=1; for(int i=2;i<=100000;i++) { if(!flag[i]) { Prime[++tot]=i; mu[i]=-1; } for(int j=1;(long long)i*Prime[j]<=100000;j++) { flag[i*Prime[j]]=true; if(i%Prime[j]==0) { mu[i*Prime[j]]=0; break; } else mu[i*Prime[j]]=mu[i]*(-1); } }}int main(){ Prepare(); while(scanf("%d",&n)!=EOF) { Max=0; memset(num,0,sizeof(num)); memset(cnt,0,sizeof(cnt)); for(int i=1;i<=n;i++) { A[i]=read(); Max=max(Max,A[i]);num[A[i]]++; } for(int i=1;i<=Max;i++) { for(int j=i;j<=Max;j+=i) cnt[i]+=num[j]; } long long Ans=0; for(int i=1;i<=Max;i++) { Ans+=(long long)mu[i]*cnt[i]*(cnt[i]-1)/2; } printf("%lld\n",Ans); } return 0;}
5.bzoj 2820 YY的GCD
莫比乌斯函数
orz Hzwer.......
在维护一个前缀和做。。。。。
#include <cstdio>#include <iostream>#include <algorithm>#include <cstring>#include <cmath>#include <queue>#include <vector>using namespace std;#define N 10000010int n,m,tot,Max;int A[N],Prime[N],mu[N],num[N],cnt[N],F[N];long long sum[N];bool flag[N];inline int read(){ int x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch<='9'&&ch>='0'){x=x*10+ch-'0';ch=getchar();} return x*f;}void Prepare(){ mu[1]=1; for(int i=2;i<=10000000;i++) { if(!flag[i]) { Prime[++tot]=i; mu[i]=-1; } for(int j=1;(long long)i*Prime[j]<=10000000;j++) { flag[i*Prime[j]]=true; if(i%Prime[j]==0) { mu[i*Prime[j]]=0; break; } else mu[i*Prime[j]]=mu[i]*(-1); } } for(int i=1;i<=tot;i++) { for(int j=Prime[i];j<=10000000;j+=Prime[i]) F[j]+=mu[j/Prime[i]]; } for(int i=1;i<=10000000;i++) sum[i]=sum[i-1]+F[i];}int main(){ Prepare(); int T=read(); while(T--) { n=read();m=read(); if(n>m)swap(n,m); long long Ans=0; for(int i=1,j;i<=n;i=j+1) //这段666 { j=min(n/(n/i),m/(m/i)); Ans+=(sum[j]-sum[i-1])*(n/i)*(m/i); } printf("%lld\n",Ans); } return 0;}
6.bzoj 2154 Crash的数字表格
#include <cstdio>#include <iostream>#include <algorithm>#include <cstring>#include <cmath>#include <queue>#include <vector>using namespace std;#define N 10000010#define Mod 20101009int n,m,tot;int Prime[N/3],F[N],mu[N];int sum[N];bool flag[N];long long Ans;void Prepare(int n){ mu[1]=1; for(int i=2;i<=n;i++) { if(!flag[i]) { Prime[++tot]=i; mu[i]=-1;F[i]=-i; } for(int j=1;(long long)i*Prime[j]<=n;j++) { flag[i*Prime[j]]=true; if(i%Prime[j]==0) { mu[i*Prime[j]]=0; break; } mu[i*Prime[j]]=mu[i]*(-1); } } for(int i=1;i<=n;i++) sum[i]=(sum[i-1]+((long long)i*i%Mod*mu[i]))%Mod;}long long Cal(int x,int y){ long long t1=(long long)(x+1)*x/2%Mod,t2=(long long)(y+1)*y/2; return t1*(t2%Mod)%Mod;}int Get(int x,int y){ long long Sum=0; for(int i=1,j;i<=x;i=j+1) { j=min(x/(x/i),y/(y/i)); long long qwer=Cal(x/i,y/i)*(sum[j]-sum[i-1])%Mod; Sum=(Sum+qwer)%Mod; } return (int)Sum;}int main(){ cin>>n>>m; if(n>m)swap(n,m); Prepare(m); for(int i=1,j;i<=n;i=j+1) { j=min(n/(n/i),m/(m/i)); long long qwer=(long long)(i+j)*(j-i+1)/2%Mod*Get(n/i,m/i)%Mod; Ans=(Ans+qwer)%Mod; } Ans=(Ans+Mod)%Mod; cout<<Ans<<endl; return 0;}
7⃣️扩展大步小步算法
bzoj 2480 Mod
真是醉了,写了个快速乘比普通的还慢。。tle了找了好久
/************************************************************** Problem: 2480 User: Edward2173 Language: C++ Result: Accepted Time:6368 ms Memory:2604 kb****************************************************************/ #include <cstdio>#include <iostream>#include <algorithm>#include <cstring>#include <cmath>#include <map>#include <queue>#include <vector>using namespace std; #define N 100010#define INF 0x3f3f3f3ftypedef long long ll; int a,b,p;int len[N]; int GCD(int a,int b){ return !b?a:GCD(b,a%b);} ll Quick_mul(ll a,ll b){ ll base=a,r=0; while(b) { if(b&1) r=(r+base)%p; base=(base+base)%p; b>>=1; } return r;} ll Quick_pow(int a,int exp){ ll base=a,r=1; while(exp) { if(exp&1) r=r*base%p; base=base*base%p; exp>>=1; } return r;} int work(int a,int b){ a%=p;b%=p; if(!b)return 0; ll Add=0,tmp=1; while(1) { int qwer=GCD(a,p); if(b%qwer!=0) return INF; if(qwer==1) break; tmp=tmp*a/qwer%p; b/=qwer;p/=qwer; Add++; if(tmp==b) return (int)Add; } map<ll,int> Hash; int Unit=sqrt((double)p+1.0),Ans=INF; ll now=b;Hash[now]=0; for(int i=1;i<Unit;i++) { now=now*a%p; Hash[now]=i; } ll base=Quick_pow(a,Unit),S_now=tmp; for(int i=1;i<=Unit+1;i++) { S_now=S_now*base%p; if(Hash.count(S_now)) return i*Unit-Hash[S_now]+(int)Add; } return Ans;} int main(){ while(scanf("%d%d%d",&a,&p,&b)) { if(a==0&&b==0&&p==0) break; int qwer=work(a,b); if(qwer==INF) printf("No Solution\n"); else printf("%d\n",qwer); } return 0;}
8⃣️斐波那契数列
codeforces 446 C 推下公式就行了
#include <cstdio>#include <iostream>#include <algorithm>#include <cstring>#include <cmath>#include <queue>#include <vector>using namespace std;#define N 300010#define Mod 1000000009LLtypedef long long ll;int n,m;ll f[N],F[N],G[N],A[N];ll a[N*4],b[N*4],sum[N*4];inline int read(){ int x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch<='9'&&ch>='0'){x=x*10+ch-'0';ch=getchar();} return x*f;}void Prepare(){ G[1]=f[1]=F[0]=F[1]=1; for(int i=2;i<=300000;i++) { f[i]=(f[i-1]+f[i-2])%Mod; F[i]=(F[i-1]+f[i-1])%Mod; G[i]=(G[i-1]+f[i])%Mod; }}void Pushup(int i){ sum[i]=(sum[i*2]+sum[i*2+1])%Mod;}void Change(int i,int len,ll v1,ll v2){ a[i]=(a[i]+v1)%Mod; b[i]=(b[i]+v2)%Mod; sum[i]=(sum[i]+F[len-1]*v1%Mod+G[len-1]*v2%Mod)%Mod;}void Pushdown(int i,int l,int r){ if(a[i]==0&&b[i]==0) return; int mid=(l+r)/2,len=mid-l+1; Change(i*2,len,a[i],b[i]); ll v1=(f[len-1]*a[i]+f[len]*b[i])%Mod,v2=(f[len]*a[i]+f[len+1]*b[i])%Mod; Change(i*2+1,r-mid,v1,v2); a[i]=b[i]=0;}void Build(int i,int l,int r){ if(l==r) { a[i]=b[i]=0;sum[i]=A[l]; return; } int mid=(l+r)/2; Build(i*2,l,mid); Build(i*2+1,mid+1,r); Pushup(i);}void Update(int i,int l,int r,int left,int right,ll v1,ll v2){ if(l>=left&&r<=right) { Change(i,r-l+1,v1,v2); return; } Pushdown(i,l,r); int mid=(l+r)/2; if(left<=mid) Update(i*2,l,mid,left,right,v1,v2); if(right>mid) { ll t1=v1,t2=v2; if(left<=mid) { int len=mid-max(left,l)+1; t1=(f[len-1]*v1+f[len]*v2)%Mod; t2=(f[len]*v1+f[len+1]*v2)%Mod; } Update(i*2+1,mid+1,r,left,right,t1,t2); } Pushup(i);}ll Query(int i,int l,int r,int left,int right){ if(l>=left&&r<=right) { return sum[i]; } Pushdown(i,l,r); int mid=(l+r)/2; if(right<=mid) return Query(i*2,l,mid,left,right); else if(left>mid) return Query(i*2+1,mid+1,r,left,right); else return (Query(i*2,l,mid,left,mid)+Query(i*2+1,mid+1,r,mid+1,right))%Mod;}int main(){ Prepare(); n=read();m=read(); for(int i=1;i<=n;i++) A[i]=read(); Build(1,1,n); for(int i=1;i<=m;i++) { int kind=read(),x=read(),y=read(); if(kind==1) Update(1,1,n,x,y,1,1); else printf("%lld\n",Query(1,1,n,x,y)); } return 0;}
暂时更到这儿了,以后再继续。。。 2016.1.23
- 数论学习
- 数论学习
- 【数论学习】数论分析证明
- 数论学习笔记 基础数论(未完成)
- 数论学习报告
- 数论剩余系学习
- 数论学习笔记
- 数论学习总结
- 数论学习总结2
- 数论学习总结《一》
- 数论概论学习笔记
- 数论学习网站备份
- 数论初步学习
- 算法学习之 数论
- 数论学习笔记
- 数论学习笔记
- lucas数论定理学习
- 数论学习笔记
- text category
- shutdown immeidate关闭oracle异常记录,查看告警信息
- Linux查看线程的堆栈信息
- linux 生成的文件或shell后面产生windows无法识别的特殊符号 解决方案
- [Leetcode]61. Rotate List @python
- 数论学习
- 线程状态与停止、阻塞(join、yield、sleep)、基本信息、优先级JAVA174-177
- android中的sp和wp
- 学习kNN算法的感受(二)
- Java中的“多态”
- 蓝懿ios技术交流和心得分享16.1.18
- 最新版本 IntelliJ IDEA 15. PyCharm 5. PhpStorm10. WebStorm 11 注册 破解
- debian配置CUDA7.5及其吐槽
- ios9不能使用http解决方法