文章目录
- 前言
- 数论数学模板
- GCD
- exgcd
- 快速幂
- 线性推逆元
- 线性推逆元(非连续)
- 逆元求组合数
- 矩阵乘法
- 线性筛素数-埃氏筛
- 线性筛素数-线性筛
- 线性筛欧拉-埃氏筛
- 线性求欧拉
- 龟速乘
- FFT
- NTT
- 分治FFT
- 多项式求逆
- 扩展中国剩余定理
- Lucas定理
- 高斯消元
- BSGS
- 拉格朗日插值
- 二次剩余
- 线性基
- 杜教筛
前言
因为老是懒得打模板的时候老是扣不到自己的标(因为之前的都打得太丑了),所以导致我十分的不爽。便打算开一个模板库。会不断更新的
数论数学模板
(某些附有证明)
GCD
我们设d=gcd(a,b)我们设d=gcd(a,b)我们设d=gcd(a,b)
∵d∣a,d∣b\because d\mid a,d\mid b∵d∣a,d∣b
∴d∣a%b\therefore d\mid a\%b∴d∣a%b
设gcd(b,a%b)=d′设gcd(b,a\%b)=d'设gcd(b,a%b)=d′
∵d′∣b,d′∣a%b\because d'\mid b,d'\mid a\%b∵d′∣b,d′∣a%b
∴d′∣a\therefore d'\mid a∴d′∣a
gcd(a,b)=gcd(b,a%b)gcd(a,b)=gcd(b,a\%b)gcd(a,b)=gcd(b,a%b)
int gcd(int a,int b)
{if (b==0){return a;}return gcd(b,a%b);
}
exgcd
ax+by=gcd(a,b)ax+by=gcd(a,b)ax+by=gcd(a,b)
bx′+(a%b)y′=gcd(b,a%b)bx'+(a\%b)y'=gcd(b,a\%b)bx′+(a%b)y′=gcd(b,a%b)
展开(a%b)(a\%b)(a%b)
bx′+(a−⌊a/b⌋b)y′=gcd(b,a%b)bx'+(a-\lfloor a/b\rfloor b)y'=gcd(b,a\%b)bx′+(a−⌊a/b⌋b)y′=gcd(b,a%b)
拆开括号
bx′+ay′−⌊a/b⌋by′=gcd(b,a%b)bx'+ay'-\lfloor a/b\rfloor by'=gcd(b,a\%b)bx′+ay′−⌊a/b⌋by′=gcd(b,a%b)
将aaa和bbb取出
ay′+b(x′−⌊a/b⌋y′)=gcd(b,a%b)ay'+b(x'-\lfloor a/b\rfloor y')=gcd(b,a\%b)ay′+b(x′−⌊a/b⌋y′)=gcd(b,a%b)
∵gcd(a,b)=gcd(b,a%b)\because gcd(a,b)=gcd(b,a\%b)∵gcd(a,b)=gcd(b,a%b)
∴ay′+b(x′−⌊a/b⌋y′)=ax+by\therefore ay'+b(x'-\lfloor a/b\rfloor y')=ax+by∴ay′+b(x′−⌊a/b⌋y′)=ax+by
将两边的aaa和bbb取出
y′+(x′−⌊a/b⌋y′)=x+yy'+(x'-\lfloor a/b \rfloor y')=x+yy′+(x′−⌊a/b⌋y′)=x+y
然后由于两边是等价的
∴{x=y′y=(x′−⌊a/b⌋y′)\therefore \left\{\begin{matrix} \\ x=y' \\ y=(x'-\lfloor a/b \rfloor y') \\ \\ \end{matrix}\right. ∴⎩⎪⎪⎨⎪⎪⎧x=y′y=(x′−⌊a/b⌋y′)
#include<cstdio>
using namespace std;
int x,y,a,b,k;
void gcd(int a,int b)
{if (b==0){x=1;y=0;return;}gcd(b,a%b);k=x;x=y;y=k-a/b*y;return;
}
int main()
{scanf("%d%d",&a,&b);gcd(a,b);printf("%d",(x+b)%b);
}
快速幂
ll power(ll x,ll b)
{if(!b) return 1;ll ans=1;while(b){if(b&1) ans=ans*x%XJQ;x=x*x%XJQ;b>>=1;}return ans;
}
线性推逆元
首先对于p,我们将其分解为ki+r(k=⌊pi⌋,r=p%r)ki+r(k=\lfloor \frac{p}{i}\rfloor,r=p\%r)ki+r(k=⌊ip⌋,r=p%r),然后有
ki+r≡0(modp)ki+r\equiv 0(mod\ \ p)ki+r≡0(mod p)
左右两边同时乘上一个i−1∗r−1i^{-1}*r^{-1}i−1∗r−1
k∗r−1+i−1≡0(modp)k*r^{-1}+i^{-1}\equiv 0(mod\ \ p)k∗r−1+i−1≡0(mod p)
i−1≡−k∗r−1(modp)i^{-1}\equiv -k*r^{-1}(mod\ \ p)i−1≡−k∗r−1(mod p)
i−1≡−⌊pi⌋∗(p%i)−1(modp)i^{-1}\equiv -\lfloor \frac{p}{i}\rfloor*(p\%i)^{-1}(mod\ \ p)i−1≡−⌊ip⌋∗(p%i)−1(mod p)
反正本来就要%p\%p%p
i−1=−⌊pi⌋∗(p%i)−1%pi^{-1}= -\lfloor \frac{p}{i}\rfloor*(p\%i)^{-1}\%pi−1=−⌊ip⌋∗(p%i)−1%p
因为iii比(p%i)(p\%i)(p%i)小,按照递推的顺序我们在求出i−1i^{-1}i−1之前就已经求出(p%i)−1(p\%i)^{-1}(p%i)−1了。但是我们还要保证不是负数,所以我们可以直接计算
i−1=p−⌊pi⌋∗(p%i)−1%pi^{-1}= p-\lfloor \frac{p}{i}\rfloor*(p\%i)^{-1}\%pi−1=p−⌊ip⌋∗(p%i)−1%p
#include<cstdio>
using namespace std;
int n,p;
long long inv[3000010];
int main()
{scanf("%d%d",&n,&p);inv[1]=1;printf("%d\n",inv[1]);for(int i=2;i<=n;i++)inv[i]=(long long)p-p/i*inv[p%i]%p,printf("%d\n",inv[i]);
}
线性推逆元(非连续)
#include<cstdio>
#include<cstring>
#include<cctype>
#include<algorithm>
#define ll long long
using namespace std;
const ll N=5e6+10;
ll n,p,K,S,a[N],s[N],k[N],ans;
__attribute__((optimize("O3"))) inline int read() {int x=0,f=1; char c=getchar();while(!isdigit(c)) {if(c=='-')f=-f;c=getchar();}while(isdigit(c)) x=(x<<1)+(x<<3)+c-48,c=getchar();return x*f;
}
ll power(ll x,ll b,ll p)
{ll ans=1;while(b){if(b&1) ans=ans*x%p;x=x*x%p;b>>=1;}return ans;
}
int main()
{n=read();p=read();K=read();S=1;k[0]=1;s[0]=1;for(int i=1;i<=n;i++){a[i]=read();S=S*a[i]%p;s[i]=S;k[i]=k[i-1]*K%p;}S=power(S,p-2,p);for(int i=n;i>=1;i--){ll inv=S*s[i-1]%p;S=S*a[i]%p;(ans+=k[i]*inv%p)%=p;}printf("%lld",ans);
}
逆元求组合数
ll power(ll x,ll b)
{ll ans=1;x%=XJQ;while(b){if(b&1) ans=ans*x%XJQ;x=x*x%XJQ;b>>=1;}return ans;
}
ll C(ll n,ll m)
{ll ans1=1,ans2=1;for(ll i=n-m+1;i<=n;i++)ans2=ans2*i%XJQ;for(ll i=1;i<=m;i++)ans1=ans1*power(i,XJQ-2)%XJQ;return ans2*ans1%XJQ;
}
矩阵乘法
struct matrix{ll a[size][size];
}f;
matrix operator *(matrix &a, matrix &b) {matrix c;memset(c.a,0,sizeof(c.a));for (ll i=0;i<size;i++)for (ll j=0;j<size;j++)for (ll k=0;k<size;k++)(c.a[i][j]+=a.a[i][k]*b.a[k][j])%=YMW;return c;
}
void ksm(matrix &f,ll b) {matrix a=f;while(b){if(b&1) a=a*f;f=f*f;b>>=1;}f=a;
}
线性筛素数-埃氏筛
void primes()
{for(ll i=2;i<=N;i++)if(!v[i]){prime[++cnt]=i;s[i]=1;//素数也标记for(ll j=2;i*j<=N;j++){if(!v[j]&&j<=i)//是素数的乘积s[i*j]=1;v[i*j]=true;}}
}
线性筛素数-线性筛
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int n,m,cnt,prime[6893911];
bool v[10000001];
int main()
{scanf("%d%d",&n,&m);v[1]=1;for(int i=2;i<=n;i++){if(!v[i]) prime[++cnt]=i;for(int j=1;j<=cnt&&i*prime[j]<=n;j++){v[prime[j]*i]=1;if(!(i%prime[j])) break;}}for(int i=1;i<=m;i++){int x;scanf("%d",&x);if(v[x]) printf("No\n");else printf("Yes\n");}
}
线性筛欧拉-埃氏筛
for (int i=2;i<=n;i++) phi[i]=i;//初始化欧拉
for (int i=2;i<=n;i++)
{if (phi[i]==i)//质数for (int j=i;j<=n;j+=i)phi[j]=phi[j]/i*(i-1);//筛去一个质因子sum+=phi[i];//统计答案
}
线性求欧拉
ll phi(ll n)//求欧拉函数
{ll ans=n;for (ll i=2;i*i<=n;i++)if (n%i==0){ans=ans/i*(i-1);while (n%i==0) n/=i;}if (n>1) ans=ans/n*(n-1);return ans;
}
龟速乘
ll ksc(ll a,ll b)
{a%=YMW;b%=YMW;ll c=(long double)a*b/YMW;ll ans=a*b-c*YMW;if(ans<0) ans+=YMW;else if(ans>=YMW) ans-=YMW;return ans;
}
FFT
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
const int N=1e6+100;
const double Pi=acos(-1);
int n,m,l,r[N<<2];
struct complex{complex(double xx=0,double yy=0){x=xx;y=yy;} double x,y;
}f[N<<2],g[N<<2];
complex operator +(complex a,complex b)
{return complex(a.x+b.x,a.y+b.y);}
complex operator -(complex a,complex b)
{return complex(a.x-b.x,a.y-b.y);}
complex operator *(complex a,complex b)
{return complex(a.x*b.x-a.y*b.y,a.x*b.y+a.y*b.x);}
void fft(complex *f,int op)
{for(int i=0;i<n;i++)if(i<r[i]){complex tmp=f[i];f[i]=f[r[i]];f[r[i]]=tmp;}for(int p=2;p<=n;p<<=1){int len=p>>1;complex tmp=complex(cos(Pi/len),sin(Pi/len)*op);for(int k=0;k<n;k+=p){complex buf(1,0);for(int i=k;i<k+len;i++){complex tt=buf*f[len+i];f[len+i]=f[i]-tt;f[i]=f[i]+tt;buf=buf*tmp;}}}
}
int main()
{scanf("%d%d",&n,&m);for(int i=0;i<=n;i++)scanf("%lf",&f[i].x);for(int i=0;i<=m;i++)scanf("%lf",&g[i].x);for(m+=n,n=1;n<=m;n<<=1);for(int i=0;i<n;i++)r[i]=(r[i>>1]>>1)|((i&1)?n>>1:0);fft(f,1);fft(g,1);for(int i=0;i<n;i++)f[i]=f[i]*g[i];fft(f,-1);for(int i=0;i<=m;i++)printf("%.0lf ",fabs(f[i].x)/n);
}
NTT
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#define ll long long
using namespace std;
const ll N=1e6+100,XJQ=998244353,G=3,Gi=332748118;
const double Pi=acos(-1);
ll n,m,l,r[N<<2],f[N<<2],g[N<<2];
ll power(ll x,ll b)
{ll ans=1;while(b){if(b&1) ans=ans*x%XJQ;x=x*x%XJQ;b>>=1;}return ans;
}
void ntt(ll *f,ll op)
{for(ll i=0;i<n;i++)if(i<r[i])swap(f[i],f[r[i]]);for(ll p=2;p<=n;p<<=1){ll len=p>>1,tmp=power(op==1?G:Gi,(XJQ-1)/p);for(ll k=0;k<n;k+=p){ll buf=1;for(ll i=k;i<k+len;i++){ll tt=buf*f[len+i]%XJQ;f[len+i]=(f[i]-tt+XJQ)%XJQ;f[i]=(f[i]+tt)%XJQ;buf=buf*tmp%XJQ;}}}
}
int main()
{scanf("%lld%lld",&n,&m);for(ll i=0;i<=n;i++) scanf("%lld",&f[i]);for(ll i=0;i<=m;i++) scanf("%lld",&g[i]);for(m+=n,n=1;n<=m;n<<=1);for(ll i=0;i<n;i++)r[i]=(r[i>>1]>>1)|((i&1)?n>>1:0);ntt(f,1);ntt(g,1);for(ll i=0;i<n;i++)f[i]=f[i]*g[i]%XJQ;ntt(f,-1);ll inv=power(n,XJQ-2);for(ll i=0;i<=m;i++)printf("%lld ",f[i]*inv%XJQ);
}
分治FFT
#include<cstdio>
#include<cstring>
#include<algorithm>
#define ll long long
using namespace std;
const ll N=1e6+10,XJQ=998244353;
ll n,g[N],f[N],a[N],b[N],R[N];
ll power(ll x,ll b){ll ans=1;while(b){if(b&1)ans=ans*x%XJQ;b>>=1;x=x*x%XJQ;}return ans;
}
void NTT(ll *f,ll logn,ll op){ll n=1<<logn;for(ll i=0;i<n;i++)if(i<R[i])swap(f[i],f[R[i]]);for(ll p=2;p<=n;p<<=1){ll len=p>>1,tmp=power(3,(XJQ-1)/p);if(op==-1)tmp=power(tmp,XJQ-2);for(ll k=0;k<n;k+=p){ll buf=1;for(ll i=k;i<k+len;i++){ll tt=buf*f[len+i]%XJQ;f[len+i]=(f[i]-tt+XJQ)%XJQ;f[i]=(f[i]+tt)%XJQ;buf=buf*tmp%XJQ;}}}if(op==-1){ll tmp=power(n,XJQ-2);for(ll i=0;i<n;i++)f[i]=f[i]*tmp%XJQ;}return;
}
void cdq(ll l,ll r,ll logn){if(!logn) return;if(l>=n)return;ll n=1<<logn,mid=l+r>>1;cdq(l,mid,logn-1);for(ll i=0;i<n;i++)R[i]=(R[i>>1]>>1)|((i&1)?n>>1:0);memset(a+(r-l)/2,0,sizeof(ll)*(r-l)/2);memcpy(a,f+l,sizeof(ll)*(r-l)/2);memcpy(b,g,sizeof(ll)*(r-l));NTT(a,logn,1);NTT(b,logn,1);for(ll i=0;i<n;i++)a[i]=a[i]*b[i]%XJQ;NTT(a,logn,-1);for(ll i=(r-l)/2;i<r-l;i++)f[l+i]=(f[l+i]+a[i])%XJQ;cdq(mid,r,logn-1);return;
}
int main()
{scanf("%lld",&n);for(ll i=1;i<n;i++)scanf("%lld",&g[i]);f[0]=1;ll logn;for(logn=0;(1<<logn)<n;logn++);cdq(0,1<<logn,logn);for(ll i=0;i<n;i++)printf("%lld ",(f[i]+XJQ)%XJQ);
}
多项式求逆
// luogu-judger-enable-o2
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#define ll long long
using namespace std;
const ll N=1e6+100,XJQ=998244353,G=3,Gi=332748118;
const double Pi=acos(-1);
ll n,m,l,a[N<<2],b[N<<2],c[N<<2],r[N<<2];
ll power(ll x,ll b)
{ll ans=1;while(b){if(b&1) ans=ans*x%XJQ;x=x*x%XJQ;b>>=1;}return ans;
}
void ntt(ll *f,ll n,ll op)
{for(ll i=0;i<n;i++)if(i<r[i])swap(f[i],f[r[i]]);for(ll p=2;p<=n;p<<=1){ll len=p>>1,tmp=power(G,(XJQ-1)/p);for(ll k=0;k<n;k+=p){ll buf=1;for(ll i=k;i<k+len;i++){ll tt=buf*f[len+i]%XJQ;f[len+i]=(f[i]-tt+XJQ)%XJQ;f[i]=(f[i]+tt)%XJQ;buf=buf*tmp%XJQ;}}}if(op==1) return;int inv=power(n,XJQ-2);reverse(f+1,f+n);for(int i=0;i<n;i++) f[i]=f[i]*inv%XJQ;
}
void work(ll *a,ll *b,ll l)
{if(l==1){b[0]=power(a[0],XJQ-2);return;}work(a,b,(l+1)>>1);ll cnt;for(cnt=1;cnt<(l<<1);cnt<<=1);for(ll i=1;i<cnt;i++)r[i]=(r[i>>1]>>1)|((i&1)?cnt>>1:0);for(ll i=0;i<l;i++) c[i]=a[i];for(ll i=l;i<cnt;i++) c[i]=0;ntt(c,cnt,1);ntt(b,cnt,1);for(ll i=0;i<cnt;i++)b[i]=(2-b[i]*c[i]%XJQ+XJQ)%XJQ*b[i]%XJQ;ntt(b,cnt,-1);for(ll i=l;i<cnt;i++) b[i]=0;
}
int main()
{scanf("%lld",&n);for(ll i=0;i<n;i++)scanf("%lld",&a[i]);work(a,b,n);for(ll i=0;i<n;i++)printf("%lld ",b[i]);
}
扩展中国剩余定理
#include<cstdio>
#include<cstring>
#include<algorithm>
#define ll long long
using namespace std;
const ll N=1e5+100;
ll n,a[N],b[N],ans;
ll ksc(ll a,ll b,ll YMW)
{a%=YMW;b%=YMW;ll c=(long double)a*b/YMW;ll ans=a*b-c*YMW;if(ans<0) ans+=YMW;else if(ans>=YMW) ans-=YMW;return ans;
}
ll exgcd(ll a,ll b,ll &x,ll &y)
{if(!b){x=1;y=0;return a;}ll d=exgcd(b,a%b,x,y),z=x;x=y;y=z-a/b*y;return d;
}
void work()
{ll x,y,k,M=b[1];ans=a[1];for(ll i=2;i<=n;i++){ll A=M,B=b[i],c=(a[i]-ans%B+B)%B;ll d=exgcd(A,B,x,y),g=B/d;if(c%d){ans=-1;return;}x=ksc(x,c/d,g);ans+=x*M;M*=g;ans=(ans%M+M)%M;}
}
int main()
{scanf("%lld",&n);for(ll i=1;i<=n;i++)scanf("%lld%lld",&b[i],&a[i]);work();printf("%lld",ans);
}
Lucas定理
#include<cstdio>
#include<cstring>
#include<algorithm>
#define ll long long
using namespace std;
ll T,n,m,p,a[110000];
ll power(ll x,ll b,ll p)
{ll ans=1;while(b){if(b&1) ans=ans*x%p;x=x*x%p;b>>=1;}return ans;
}
ll C(ll n,ll m,ll p)
{if(m>n) return 0ll;return a[n]*power(a[m],p-2,p)%p*power(a[n-m],p-2,p)%p;
}
ll lucas(ll n,ll m,ll p)
{if(!m) return 1ll;return lucas(n/p,m/p,p)*C(n%p,m%p,p)%p;
}
int main()
{scanf("%lld",&T);while(T--){scanf("%lld%lld%lld",&n,&m,&p);a[0]=1;for(ll i=1;i<=p;i++)a[i]=a[i-1]*i%p;printf("%lld\n",lucas(n+m,m,p));}return 0;
}
高斯消元
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
const int N=110;
int n;
double b[N],c[N][N];
int main()
{scanf("%d",&n);for(int i=1;i<=n;i++){for(int j=1;j<=n;j++)scanf("%lf",&c[i][j]);scanf("%lf",&b[i]);}for(int i=1;i<=n;i++){int z=i;for(int j=i+1;j<=n;j++){if(fabs(c[j][i])>fabs(c[z][i]))z=j;}for(int j=1;j<=n;j++)swap(c[i][j],c[z][j]);swap(b[i],b[z]);if(!c[i][i]){printf("No Solution\n");return 0;}for(int j=1;j<=n;j++){if(i==j) continue;double rate=c[j][i]/c[i][i];for(int k=i;k<=n;k++)c[j][k]-=c[i][k]*rate;b[j]-=b[i]*rate; }}for(int i=1;i<=n;i++)printf("%.2lf\n",b[i]/c[i][i]);
}
BSGS
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<map>
#define ll long long
using namespace std;
ll p,b,n,ans=1e18,t;
map<ll,ll> v;
ll power(ll x,ll b)
{ll ans=1;while(b){if(b&1) ans=ans*x%p;x=x*x%p;b>>=1;}return ans;
}
int main()
{scanf("%lld%lld%lld",&p,&n,&b);t=(int)sqrt(p)+1;for(ll i=0;i<t;i++){ll val=b*power(n,i)%p;v[val]=i;}n=power(n,t);if(n==0) {if(!b) printf("1");else printf("no solution");return 0;}for(ll i=0;i<=t;i++){ll val=power(n,i);ll j=v.find(val)==v.end()?-1:v[val];if(j>=0&&i*t-j>=0) ans=min(ans,i*t-j);}if(ans==1e18) printf("no solution");else printf("%lld",ans);
}
拉格朗日插值
#include<cstdio>
#include<cstring>
#include<algorithm>
#define ll long long
using namespace std;
const ll N=2e3+10,XJQ=998244353;
ll n,k,x[N],y[N],ans;
ll power(ll x,ll b){x%=XJQ;ll ans=1;while(b){if(b&1)ans=ans*x%XJQ;x=x*x%XJQ;b>>=1;}return ans;
}
int main()
{scanf("%lld%lld",&n,&k);for(ll i=1;i<=n;i++)scanf("%lld%lld",&x[i],&y[i]);for(ll i=1;i<=n;i++){for(ll j=1;j<=n;j++)if(i!=j)(y[i]*=(k-x[j]+XJQ)%XJQ*power(x[i]-x[j]+XJQ,XJQ-2)%XJQ)%=XJQ;(ans+=y[i])%=XJQ; }printf("%lld",ans);
}
二次剩余
#include<cstdio>
#include<cstring>
#include<algorithm>
#define ll long long
using namespace std;
ll T,n,p,k,w;
struct complex{complex(ll xx=0,ll yy=0){x=xx;y=yy;}ll x,y;
};
complex operator+(complex &a,complex &b)
{return complex((a.x+b.x)%p,(a.y+b.y)%p);}
complex operator-(complex &a,complex &b)
{return complex((a.x-b.x+p)%p,(a.y-b.y+p)%p);}
complex operator*(complex &a,complex &b)
{return complex((a.x*b.x%p+a.y*b.y%p*w%p+p)%p,(a.x*b.y+a.y*b.x)%p);}
complex poweri(complex x,ll b){complex ans=complex(1,0);while(b){if(b&1)ans=ans*x;x=x*x;b>>=1; }return ans;
}
ll power(ll x,ll b){ll ans=1;while(b){if(b&1)ans=ans*x%p;x=x*x%p;b>>=1;}return ans;
}
bool check(ll a)
{return power(((a*a%p-n)%p+p)%p,k)==(p-1);}
int main()
{srand(31958);scanf("%lld",&T);while(T--){scanf("%lld%lld",&n,&p);if(!n){printf("0\n");continue;}if(p==2){printf("%lld\n",n);continue;}k=(p-1)>>1;if(power(n,k)==p-1){printf("Hola!\n");continue;}ll a=rand()%p;while(!check(a))a=rand()%p;w=((a*a%p-n)%p+p)%p;ll x1=poweri(complex(a,1),(p+1)/2).x;ll x2=p-x1;if(x1>x2)swap(x1,x2);if(x1!=x2)printf("%lld %lld\n",x1,x2);else printf("%lld\n",x1);}
}
线性基
#include<cstdio>
#include<cstring>
#include<algorithm>
#define ll long long
using namespace std;
ll n,d[60];
void add(ll x){for(ll i=51;i>=0;i--){if(x&(1ll<<i)){if(d[i])x^=d[i];else{d[i]=x;break;}}}return;
}
int main()
{scanf("%lld",&n);for(ll i=1;i<=n;i++){ll x;scanf("%lld",&x);add(x);}ll ans=0;for(ll i=51;i>=0;i--)if(ans<(ans^d[i]))ans=ans^d[i];printf("%lld",ans);
}
杜教筛
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<map>
#define ll long long
using namespace std;
const ll N=1e7+1;
ll T,n,cnt,mu[N],phi[N],pri[N];
bool vis[N];
map<ll,ll> sp,sm;
void prime(){mu[1]=phi[1]=1;for(ll i=2;i<N;i++){if(!vis[i])pri[++cnt]=i,mu[i]=-1,phi[i]=i-1;for(ll j=1;j<=cnt&&pri[j]*i<N;j++){vis[pri[j]*i]=1;if(i%pri[j]==0){phi[i*pri[j]]=phi[i]*pri[j];break;}phi[i*pri[j]]=phi[pri[j]]*phi[i];mu[i*pri[j]]=-mu[i];}}for(ll i=1;i<N;i++)phi[i]+=phi[i-1],mu[i]+=mu[i-1];return;
}
ll GetSphi(ll n){if(n<N)return phi[n];if(sp[n])return sp[n];ll rest=n*(n+1ll)/2ll;for(ll l=2ll,r;l<=n;l=r+1ll)r=n/(n/l),rest-=(r-l+1ll)*GetSphi(n/l);return (sp[n]=rest);
}
ll GetSmul(ll n){if(n<N)return mu[n];if(sm[n])return sm[n];ll rest=1ll;for(ll l=2ll,r;l<=n;l=r+1ll)r=n/(n/l),rest-=(r-l+1ll)*GetSmul(n/l);return (sm[n]=rest);
}
int main()
{scanf("%lld",&T);prime();while(T--){scanf("%lld",&n);printf("%lld %lld\n",GetSphi(n),GetSmul(n));}
}