数学模板整理
一些NOIP难度的
exgcd
#include<cstdio> #include<cstring> #include<algorithm> #include<iostream> using namespace std; typedef long long ll; ll a,b,x,y; void exgcd(ll a,ll b,ll&x,ll&y) { if(!b){x=1,y=0;return;} exgcd(b,a%b,y,x); y-=a/b*x; } int main() { cin>>a>>b; exgcd(a,b,x,y); if(a*x+b*y==1)cout<<(x+b)%b;else cout<<(y+b)%b; }
excrt(今年考的可能性不大因为NOI2018考过了,不过还是复习万一能骗分呢?):https://www.luogu.org/problemnew/show/P4777
#include<bits/stdc++.h> using namespace std; typedef long long ll; const int N=1e5+7; int n; ll a[N],b[N]; ll qmul(ll a,ll b,ll mod) { ll ret=0; while(b>0) { if(b&1)ret=(ret+a)%mod; a=(a+a)%mod,b>>=1; } return ret; } ll exgcd(ll a,ll b,ll&x,ll&y) { if(!b){x=1,y=0;return a;} ll ret=exgcd(b,a%b,y,x);y-=a/b*x; return ret; } ll excrt() { ll x,y,k,lcm=a[1],ans=b[1]; for(int i=2;i<=n;i++) { ll A=lcm,B=a[i],c=(b[i]-ans%B+B)%B,d=exgcd(A,B,x,y); if(c%d)return -1; x=qmul(x,c/d,B/d); ans+=x*lcm,lcm*=B/d; ans=(ans%lcm+lcm)%lcm; } return(ans%lcm+lcm)%lcm; } int main() { scanf("%d",&n); for(int i=1;i<=n;i++)scanf("%lld%lld",&a[i],&b[i]); printf("%lld",excrt()); }
数论分块+莫比乌斯反演:https://www.lydsy.com/JudgeOnline/problem.php?id=2301
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int maxn=100000; bool check[maxn+10]; int pri[maxn+10],mu[maxn+10],s[maxn+10]; void moblus() { memset(check,0,sizeof(check)); mu[1]=1; int tot=0; for(int i=2;i<=maxn;i++) { if(!check[i]) pri[tot++]=i,mu[i]=-1; for(int j=0;j<tot;j++) { if(i*pri[j]>maxn)break; check[i*pri[j]]=1; if(i%pri[j]==0) { mu[i*pri[j]]=0; break; } else mu[i*pri[j]]=-mu[i]; } } } long long solve(int n,int m) { long long ans=0; if(n>m)swap(n,m); for(int i=1,l=0;i<=n;i=l+1) { l=min(n/(n/i),m/(m/i)); ans+=(long long)(s[l]-s[i-1])*(n/i)*(m/i); } return ans; } int main() { moblus(); for(int i=1;i<=maxn;i++) s[i]=s[i-1]+mu[i]; int t,a,b,c,d,k; scanf("%d",&t); while(t--) { scanf("%d%d%d%d%d",&a,&b,&c,&d,&k); printf("%lld\n",solve(b/k,d/k)-solve((a-1)/k,d/k)-solve(b/k,(c-1)/k)+solve((a-1)/k,(c-1)/k)); } }
sg函数:https://www.luogu.org/problemnew/show/P3235
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; int T,F,n,sum,sg[100010]; int getsg(int u) { if(sg[u]!=-1)return sg[u]; int r,k,now; bool ext[10010]={}; for(int i=2,j;i<=u;i=j+1) { j=min(u/(u/i),u),now=0; r=u/i,k=u%i; if(i>=j) { if(k&1)now^=getsg(r+1); if((i-k)&1)now^=getsg(r); ext[now]=1; } else if(r&1) { if((i-k)&1)now^=getsg(r); ext[now]=1,now^=getsg(r+1),ext[now]=1; } else{ if(k&1)now^=getsg(r+1); ext[now]=1,now^=getsg(r),ext[now]=1; } } for(int i=0;;i++)if(!ext[i])return sg[u]=i; } int main() { memset(sg,-1,sizeof sg); scanf("%d%d",&T,&F); for(int i=0;i<F;i++)sg[i]=0; while(T--) { scanf("%d",&n); int sum=0;for(int i=1,x;i<=n;i++)scanf("%d",&x),sum^=getsg(x); if(!sum)printf("0 ");else printf("1 "); } }
应该没了吧?
以下是NOI难度的……
线性基:https://www.luogu.org/problemnew/show/P3812
#include<bits/stdc++.h> #define ll long long using namespace std; const int N=200; int n; ll a[N],b[N],ans; int main() { scanf("%d",&n); for(int i=1;i<=n;i++)scanf("%lld",&a[i]); for (int i=1;i<=n;i++) { for(int k=52;~k;k--) if(a[i]&(1ll<<k)) { if(!b[k]){b[k]=a[i];break;} else a[i]^=b[k]; } } for(int i=52;~i;i--) if((ans^b[i])>ans)ans^=b[i]; printf("%lld",ans); }
BSGS:https://www.lydsy.com/JudgeOnline/problem.php?id=2242
#include<bits/stdc++.h> using namespace std; typedef long long ll; map<int,int>hsh; ll y,z,p; ll qpow(ll a,ll b) { a%=p; ll ret=1; while(b) { if(b&1)ret=ret*a%p; a=a*a%p,b>>=1; } return ret; } ll exgcd(ll a,ll b,ll&x,ll&y) { if(b==0){x=1,y=0;return a;} ll ret=exgcd(b,a%b,y,x);y-=a/b*x; return ret; } void solve2(ll a,ll b) { ll x,y,ans,d,s; d=exgcd(a,p,x,y); if(b%d){puts("Orz, I cannot find x!");return;} ans=b/d*x; s=p/d; ans=(ans%s+s)%s; printf("%lld\n",ans); } void solve3() { y%=p,z%=p; if(!y) { if(!z)puts("1");else puts("Orz, I cannot find x!"); return; } ll m=ceil(sqrt(p)),v=qpow(y,p-m-1),e=1,ret; hsh.clear(); hsh[1]=m+1; for(ll i=1;i<=m;i++) { e=e*y%p; if(!hsh[e])hsh[e]=i; } ret=-1; for(ll i=0;i<m;i++) { if(hsh[z]){ret=i*m+(hsh[z]==m+1?0:hsh[z]);break;} z=z*v%p; } if(ret==-1)puts("Orz, I cannot find x!"); else printf("%d\n",ret); } int main() { int T,k; scanf("%d%d",&T,&k); while(T--) { scanf("%lld%lld%lld",&y,&z,&p); if(k==1)printf("%lld\n",qpow(y,z)); else if(k==2)solve2(y,z); else solve3(); } }
exBSGS:https://www.luogu.org/problemnew/show/P4195
#include<bits/stdc++.h> using namespace std; unordered_map<int,int>h; int gcd(int a,int b){return b?gcd(b,a%b):a;} int exbsgs(int A,int B,int p) { if(B==1)return 0; int cnt=0,d,k=1,q,v; while((d=gcd(A,p))!=1) { if(B%d)return -1; B/=d,p/=d,++cnt; k=1ll*k*(A/d)%p; if(k==B)return cnt; } q=ceil(sqrt(p)),v=1; h.clear(); for(int i=0;i<q;i++)h[1ll*v*B%p]=i,v=1ll*v*A%p; k=1ll*k*v%p; for(int i=1;i<=q;i++) { if(h.find(k)!=h.end())return i*q-h[k]+cnt; k=1ll*k*v%p; } return -1; } int main() { int a,p,b; while(scanf("%d%d%d",&a,&p,&b),a||p||b) { int ans=exbsgs(a,b,p); if(ans!=-1)printf("%d\n",ans);else puts("No Solution"); } }
杜教筛:https://www.luogu.org/problemnew/show/P4213
#include<bits/stdc++.h> #define R register using namespace std; typedef long long ll; const int N=5e6+100; unordered_map<int,ll>ansphi,ansmu; int cnt,vis[N],pri[N]; ll mu[N],phi[N]; void prepare() { mu[1]=phi[1]=1; for(int i=2;i<N;i++) { if(!vis[i])pri[++cnt]=i,mu[i]=-1,phi[i]=i-1; for(int j=1;j<=cnt&&i*pri[j]<N;j++) { vis[i*pri[j]]=1; if(i%pri[j]==0){mu[i*pri[j]]=0,phi[i*pri[j]]=phi[i]*pri[j];break;} else mu[i*pri[j]]=-mu[i],phi[i*pri[j]]=phi[i]*phi[pri[j]]; } } for(int i=1;i<N;i++)mu[i]+=mu[i-1],phi[i]+=phi[i-1]; } ll getphi(int n) { if(n<N)return phi[n]; if(ansphi[n])return ansphi[n]; ll ans=0; for(R int l=2,r;l<=n&&r<INT_MAX;l=r+1)r=n/(n/l),ans+=(r-l+1)*getphi(n/l); return ansphi[n]=(n+1ll)*n/2-ans; } ll getmu(int n) { if(n<N)return mu[n]; if(ansmu[n])return ansmu[n]; ll ans=0; for(R int l=2,r;l<=n&&r<INT_MAX;l=r+1)r=n/(n/l),ans+=(r-l+1)*getmu(n/l); return ansmu[n]=1-ans; } int main() { prepare(); int T;scanf("%d",&T); while(T--) { int n;scanf("%d",&n); printf("%lld %lld\n",getphi(n),getmu(n)); } }
洲阁筛:https://www.luogu.org/problemnew/show/SP20174
#include<bits/stdc++.h> using namespace std; typedef long long ll; const int N=1e6+7; int cnt,cntp[N],pri[N],D3[N],low[N],vis[N],L0[N],L1[N]; ll g0[N],g1[N],f0[N],f1[N]; void prepare() { D3[1]=1; for(int i=2;i<=1e6;i++) { if(!vis[i])pri[cnt++]=i,D3[i]=4,low[i]=i; for(int j=0;j<cnt&&i*pri[j]<=1e6;j++) { vis[i*pri[j]]=1; if(i%pri[j]==0) { D3[i*pri[j]]=(i/low[i]==1)?(D3[i]+3):(D3[i/low[i]]*D3[low[i]*pri[j]]); low[i*pri[j]]=low[i]*pri[j]; break; } D3[i*pri[j]]=D3[i]*4,low[i*pri[j]]=pri[j]; } } } void getG(int b,int pn,ll n) { for(int i=1;i<b;i++)g0[i]=i,g1[i]=n/i; for(int i=0;i<pn;++i) { for(int j=1;j<b&&i<L1[j];j++) { ll y=n/j/pri[i]; g1[j]-=((y<b)?(g0[y]-max(0,min(i,cntp[y])-L0[y])):(g1[n/y]-max(0,i-L1[n/y]))); } for(int j=b-1;j&&i<L0[j];j--) { ll y=j/pri[i]; g0[j]-=g0[y]-max(0,min(i,cntp[y])-L0[y]); } } for(int i=1;i<b;++i)g0[i]-=cntp[i]-L0[i]+1,g1[i]-=max(0,pn-L1[i])+1; for(int i=1;i<b;++i)g0[i]*=4,g1[i]*=4; } void getF(int b,int pn,ll n) { for(int i=1;i<b;i++)f0[i]=f1[i]=1; for(int i=pn-1;~i;i--) { for(int j=1;j<b&&i<L1[j];j++) { ll y=n/j/pri[i]; for(int c=1;y;y/=pri[i],c++) if(y<b)f1[j]+=(3*c+1)*(f0[y]+4*max(0,cntp[y]-max(i+1,L0[y]))); else f1[j]+=(3*c+1)*(f1[n/y]+4*max(0,pn-max(i+1,L1[n/y]))); } for(int j=b-1;j&&i<L0[j];j--) { int y=j/pri[i]; for(int c=1;y;y/=pri[i],c++) f0[j]+=(3*c+1)*(f0[y]+4*max(0,cntp[y]-max(i+1,L0[y]))); } } for(int i=1;i<b;++i)f0[i]+=4*max(0,cntp[i]-L0[i]),f1[i]+=4*(pn-L1[i]); } ll getsum(ll n) { int b=1,pn=0; while(1ll*b*b<=n)b++; while(1ll*pri[pn]*pri[pn]<=n)pn++; L0[0]=0; for(int i=1;i<b;i++) { L0[i]=L0[i-1]; while(1ll*pri[L0[i]]*pri[L0[i]]<=i)L0[i]++; } L1[b]=0; for(int i=b-1;i;i--) { ll x=n/i;L1[i]=L1[i+1]; while(1ll*pri[L1[i]]*pri[L1[i]]<=x)L1[i]++; } cntp[0]=0; for(int i=1;i<b;i++) { cntp[i]=cntp[i-1]; while(pri[cntp[i]]<=i)cntp[i]++; } getG(b,pn,n),getF(b,pn,n); ll ret=f1[1]; for(int i=1;i<b;i++)ret+=D3[i]*g1[i]; return ret; } int main() { prepare(); int T;scanf("%d",&T); ll n;while(T--)scanf("%lld",&n),printf("%lld\n",getsum(n)); }
min25筛:loj.ac/problem/6053
#include<bits/stdc++.h> using namespace std; typedef long long ll; const int N=1e5+1000,mod=1e9+7,inv2=500000004; ll n,P,cnt,id1[N],id2[N],w[2*N],m,g[2*N],h[2*N],f[2*N],pri[N],pre[N],vis[N]; void init() { for(int i=2;i<=1e5;++i) { if(!vis[i])pri[++cnt]=i,pre[cnt]=(pre[cnt-1]+i)%mod; for(int j=1;j<=cnt&&i*pri[j]<=1e5;++j) { vis[i*pri[j]]=1; if(i%pri[j]==0)break; } } } int getid(ll x){return x<=P?id1[x]:id2[n/x];} void calc() { ll v,r; for(ll l=1;l<=n;l=r+1) { v=n/l,r=n/v; if(v<=P)id1[v]=++m;else id2[r]=++m; w[m]=v; ll z=v%mod; g[m]=(z+2)*(z-1)%mod*inv2%mod; h[m]=z-1; } for(ll i=1;i<=cnt;++i) for(ll j=1;j<=m&&pri[i]*pri[i]<=w[j];++j) { int op=getid(w[j]/pri[i]); g[j]=(g[j]-pri[i]*(g[op]-pre[i-1])%mod)%mod; h[j]=(h[j]-(h[op]-i+1))%mod; } for(int i=1;i<=m;++i)g[i]=(g[i]+mod)%mod,f[i]=(f[i]+mod)%mod,f[i]=(g[i]-h[i])%mod; } ll ask(ll x,ll i) { if(x<=1||x<pri[i])return 0; ll ans=f[getid(x)]-(pre[i-1]-i+1); if(i==1)ans+=2; for(int j=i;j<=cnt&&pri[j]*pri[j]<=x;++j) { ll r=pri[j]; for(ll e=1;r*pri[j]<=x;++e,r*=pri[j]) ans=(ans+(pri[j]^e)*ask(x/r,j+1)+(pri[j]^(e+1)))%mod; } return ans; } int main() { cin>>n;P=sqrt(n); init(); calc(); printf("%lld",((ask(n,1)+1)%mod+mod)%mod); }
Miller_Rabin&Pollar_Rho:https://www.lydsy.com/JudgeOnline/problem.php?id=3667
#include<bits/stdc++.h> using namespace std; typedef long long ll; vector<ll>fac; ll mult(ll a,ll b,ll mod){return((a*b-(ll)(((long double)a*b+0.5)/mod)*mod)%mod+mod)%mod;} ll qpow(ll a,ll b,ll mod) { ll ret=1; while(b) { if(b&1)ret=mult(ret,a,mod); a=mult(a,a,mod),b>>=1; } return ret; } bool Miller_Rabin(ll x) { if(x==2)return 1; int tim=10; while(tim--) { ll a=rand()%(x-2)+2,p,nw; if(qpow(a,x-1,x)!=1)return 0; p=x-1; while(!(p&1)) { p>>=1,nw=qpow(a,p,x); if(nw!=1&&nw!=x-1&&mult(nw,nw,x)==1)return 0; } } return 1; } ll Pollard_rho(ll n,int c) { ll k=2,x=rand()%(n-1)+1,y=x,d; for(int i=1;;++i) { x=(mult(x,x,n)+c)%n; d=__gcd((y-x+n)%n,n); if(d!=1&&d!=n)return d; if(x==y)return n; if(i==k)y=x,k<<=1; } } void Fact(ll n,int c) { if(n==1)return; if(Miller_Rabin(n)){fac.push_back(n);return;} ll p=n; while(p>=n)p=Pollard_rho(n,c--); Fact(p,c);Fact(n/p,c); } int main() { int T;cin>>T; while(T--) { ll n;cin>>n; if(n==1){puts("1");continue;} fac.clear(),Fact(n,233); sort(fac.begin(),fac.end()); if(fac.size()==1)puts("Prime"); else printf("%lld\n",fac[fac.size()-1]); } }
高斯消元:https://www.luogu.org/problemnew/show/P3389
#include<bits/stdc++.h> using namespace std; const double eps=1e-8; int n,m,ans; double a[110][110],x[110]; int main() { scanf("%d",&n); for(int i=1;i<=n;i++) for(int j=1;j<=n+1;j++) scanf("%lf",&a[i][j]); //Gauss消元,求实数解 for(int i=1;i<=n;i++) { int k=i; for(int j=i;j<=n;j++) if(fabs(a[j][i])-fabs(a[k][i])>eps)k=j;//选择当前要消的列中绝对值最大的行 if(i!=k) for(int j=1;j<=n+1;j++)swap(a[i][j],a[k][j]); if(fabs(a[i][i])<eps){printf("No Solution\n");return 0;} for(int j=i+1;j<=n+1;j++)a[i][j]/=a[i][i]; for(int j=1;j<=n;j++) if(i!=j)for(int k=i+1;k<=n+1;k++) a[j][k]-=a[j][i]*a[i][k]; } for(int i=1;i<=n;i++)printf("%.2lf\n",a[i][n+1]); }
矩阵求逆:https://www.luogu.org/problemnew/show/P4783
#include<bits/stdc++.h> using namespace std; const int N=404,mod=1e9+7; int n,m,a[N][N<<1]; int qpow(int a,int b) { int ret=1; while(b) { if(b&1)ret=1ll*ret*a%mod; a=1ll*a*a%mod,b>>=1; } return ret; } int main() { scanf("%d",&n); m=n<<1; for(int i=1;i<=n;i++) { for(int j=1;j<=n;j++)scanf("%d",&a[i][j]); a[i][n+i]=1; } for(int i=1;i<=n;++i) { for(int j=i;j<=n;++j) if(a[j][i]) { for(int k=1;k<=m;++k)swap(a[i][k],a[j][k]); break; } if(!a[i][i]){puts("No Solution");return 0;} int r=qpow(a[i][i],mod-2); for(int j=i;j<=m;++j)a[i][j]=1ll*a[i][j]*r%mod; for(int j=1;j<=n;++j) if(j!=i) { r=a[j][i]; for(int k=i;k<=m;++k)a[j][k]=(a[j][k]-1ll*r*a[i][k]%mod+mod)%mod; } } for(int i=1;i<=n;i++) { for(int j=n+1;j<=m;j++)printf("%d ",a[i][j]); puts(""); } }
exLucas:https://www.luogu.org/problemnew/show/P4720
#include<bits/stdc++.h> using namespace std; typedef long long ll; const int N=1e6+7; ll n,m,p,fac[N],PI[N],PK[N],cnt; ll qpow(ll a,ll b,ll p) { ll ret=1; while(b) { if(b&1)ret=ret*a%p; a=a*a%p;b>>=1; } return ret; } void exgcd(ll a,ll b,ll &x,ll &y) { if(!b){x=1;y=0;return;} exgcd(b,a%b,y,x);y-=a/b*x; } ll inv(ll n,ll p) { ll a=n,b=p,x,y; exgcd(a,b,x,y); x=(x%b+b)%b; if(!x)x+=b; return x; } ll mul(ll n,ll pi,ll pk) { if(!n)return 1; ll ans=1; if(n/pk)ans=ans*fac[pk]%pk,ans=qpow(ans,n/pk,pk)%pk; ans=ans*fac[n%pk]%pk; return ans*mul(n/pi,pi,pk)%pk; } ll C(ll n,ll m,ll p,ll pi,ll pk) { if(n<m)return 0; int k=0;ll ans=1; fac[0]=fac[1]=1; for(int i=2;i<=pk;i++) if(i%pi)fac[i]=fac[i-1]*i%pk; else fac[i]=fac[i-1]; ll a=mul(n,pi,pk),b=mul(m,pi,pk),c=mul(n-m,pi,pk); for(ll i=n;i;i/=pi)k+=i/pi; for(ll i=m;i;i/=pi)k-=i/pi; for(ll i=n-m;i;i/=pi)k-=i/pi; ans=a*inv(b,pk)%pk*inv(c,pk)%pk*qpow(pi,k,pk)%pk; return ans*(p/pk)%p*inv(p/pk,pk)%p; } ll CRT(ll n,ll m,ll p) { if(n<m)return 0; ll ans=0; for(int i=1;i<=cnt;i++)ans=(ans+C(n,m,p,PI[i],PK[i]))%p; return ans; } void prepare(int p) { cnt=0; for(int i=2;i*i<=p;++i) if(p%i==0) { PI[++cnt]=i;PK[cnt]=1; while(p%i==0)p/=i,PK[cnt]*=i; } if(p!=1)PI[++cnt]=PK[cnt]=p; } int main() { cin>>n>>m>>p; prepare(p); cout<<CRT(n,m,p); }
未完待续……