数论模板

Posted Achen

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了数论模板相关的知识,希望对你有一定的参考价值。

翘了一上午课来机房皮。

技术分享
//Twenty
#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<queue>
#include<vector>
const int maxn=10000000+5;
int x,tot,prime[maxn],shs[maxn];
using namespace std;
int n,m;
void work(){
    for(int i=2;i<=n;i++){
        if(!shs[i]) prime[++tot]=i;
        for(int j=1;j<=tot&&prime[j]*i<=n;j++){
            shs[prime[j]*i]=1;
            if(i%prime[j]==0) break;
        }
    }
}
int main()
{
   scanf("%d%d",&n,&m);
   work();
   for(int i=1;i<=m;i++){
       scanf("%d",&x);
       if(shs[x]||x==1) printf("No\n");
       else printf("Yes\n");
   }
   return 0;
}
线性筛素数
技术分享
//Twenty
#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<queue>
#include<vector>
using namespace std;
typedef long long ll;
ll n,p;
ll ksm(ll a,ll b){
    ll base=a,res=1;
    while(b){
        if(b&1) (res*=base)%=p;
        (base*=base)%=p;
        b>>=1;
    }
    return res;
}
int main()
{
   scanf("%d%d",&n,&p);
   for(int i=1;i<=n;i++){
   printf("%lld\n",ksm((ll)i,(ll)p-2));
   }
   return 0;
}
费马小定理求乘法逆元
技术分享
//Twenty
#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<queue>
#include<vector>
using namespace std;
int n,p;
void exgcd(int a,int b,int &d,int &x,int &y){
    if(b==0) {d=a,x=1,y=0;return ;}
    exgcd(b,a%b,d,y,x); y-=x*(a/b);
}
int inv(int a,int n){
    int d,x,y;
    exgcd(a,n,d,x,y);
    return d==1?(x+n)%n:-1;
}
int main()
{
   scanf("%d%d",&n,&p);
   for(int i=1;i<=n;i++){
   printf("%d\n",inv(i,p));
   }
   return 0;
}
扩展欧几里得求乘法逆元
技术分享
//Twenty
#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<queue>
#include<vector>
const int maxn=1e7;
using namespace std;
long long inv[maxn];
long long n,p;
int main()
{
   scanf("%lld%lld",&n,&p);
   inv[1]=1;
   printf("%lld\n",inv[1]);
   for(int i=2;i<=n;i++)
   {inv[i]=(p-p/i)*inv[p%i]%p;
    printf("%lld\n",inv[i]);}
   return 0;
}
线性求乘法逆元
技术分享
//Twenty
#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<queue>
#include<vector>
const int maxn=10000+5;
int x,tot,prime[maxn],shs[maxn];
using namespace std;
int n,m;
int query(int x){
    int mi=sqrt(x),res=x;
    for(int i=2;i<=mi;i++) if(x%i==0){
        res=res-res/i;
        while(x%i==0) x/=i;
    }
    if(x!=1) res=res-res/x;
    return res;
}
int main()
{
   scanf("%d",&n);
   for(int i=1;i<=n;i++){
       scanf("%d",&x);
       printf("%d\n",query(x));
   }
   return 0;
}
单个求欧拉函数
技术分享
//Twenty
#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<queue>
#include<vector>
const int maxn=32768+5;
int x,tot,prime[maxn],shs[maxn],ol[maxn];
using namespace std;
int n,m;
int work(){
    for(int i=2;i<=maxn;i++){
        if(!shs[i]) {prime[++tot]=i;ol[i]=i-1;}
        for(int j=1;j<=tot&&prime[j]*i<=maxn;j++){
            shs[prime[j]*i]=1;
            if(i%prime[j]==0){
                ol[prime[j]*i]=ol[i]*prime[j];
                break;
            }
            else ol[prime[j]*i]=ol[i]*(prime[j]-1);
        }
    }
}
int main()
{
   scanf("%d",&n);
   work();
   for(int i=1;i<=n;i++){
       scanf("%d",&x);
       printf("%d\n",ol[x]);
   }
   return 0;
}
线性筛欧拉函数
技术分享
//Twenty
#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<queue>
#include<vector>
using namespace std;
long long ans,n,a[65],b[65];
int main()
{
    scanf("%lld",&n);
    for(int i=1;i<=n;i++) scanf("%lld",&a[i]);
    for(int i=1;i<=n;i++)
        for(int j=60;j>=0;j--) {
            if((1LL<<j)&a[i]) {
                if(b[j]) a[i]^=b[j];
                else {b[j]=a[i]; break;}
            }
        } 
    for(int i=60;i>=0;i--)
        if((ans^b[i])>ans) ans^=b[i];
    cout<<ans;
    return 0;
}
线性基
技术分享
//Twenty
#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<queue>
#include<vector>
using namespace std;
const int maxn=1e5+299;
typedef long long LL;
LL T,n,m,p,c[maxn];
LL ksm(LL a,LL b){
    a%=p;
    LL res=1,base=a;
    while(b){
        if(b&1) (res*=base)%=p;
        (base*=base)%=p;
        b>>=1;
    }
    return res;
}
LL C(LL n,LL m){
    if(n<m) return 0;
    return (c[n]*ksm(c[m],p-2)%p*ksm(c[n-m],p-2))%p;
}
LL lucas(LL n,LL m){
    if(!m) return 1;
    return (C(n%p,m%p)*lucas(n/p,m/p))%p;
}
int main()
{
    scanf("%lld",&T);
    while(T--){
    scanf("%lld%lld%lld",&n,&m,&p);
    c[0]=1;
    for(int i=1;i<=p;i++)
    c[i]=(c[i-1])*i%p;
    printf("%lld\n",lucas(n+m,m));
    }
   return 0;
}
卢卡斯定理
技术分享
//Twenty
#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<queue>
#include<vector>
using namespace std;
const int maxn=50000+299;
int T,a,b,c,d,k,tot,bo[maxn],prime[maxn],mu[maxn],sum[maxn]; 
void make_mu(){
    mu[1]=1; sum[1]=1;
    for(int i=2;i<=maxn;i++){
        if(!bo[i]) {prime[++tot]=i; mu[i]=-1;}
        for(int j=1;j<=tot&&prime[j]*i<=maxn;j++){
            if(i%prime[j]==0){
                bo[prime[j]*i]=1;
                mu[prime[j]*i]=0;
                break;
            }
            else {
            bo[prime[j]*i]=1;
            mu[prime[j]*i]=mu[i]*(-1);
            }
        }
        sum[i]=sum[i-1]+mu[i];
    }
}
int f(int n,int m){
    n/=k; m/=k;
    int t=min(n,m),last,ans=0;
    for(int i=1;i<=t;i=last+1){
        last=min(n/(n/i),m/(m/i));
        ans+=(sum[last]-sum[i-1])*(n/i)*(m/i);    
    }
    return ans;
}
int cul(int a,int b,int c,int d){
    int res=0; 
    res+=f(b,d);
    res-=f(a-1,d);
    res-=f(b,c-1);
    res+=f(a-1,c-1);
    return res;
}
int main()
{
   scanf("%d",&T);
   make_mu();
   while(T--){
       scanf("%d%d%d%d%d",&a,&b,&c,&d,&k);
       printf("%d\n",cul(a,b,c,d));
   }
   return 0;
}
莫比乌斯反演
技术分享
//Twenty
#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<queue>
#include<vector>
const int maxn=1e6+299;
const int mod=1e9+7;
int prime[maxn*2],bo[maxn*2],tot,nxt[maxn*2],pr[20];
typedef long long LL;
LL nn,xx,n,ans;
using namespace std;
void pre(){
    for(int i=2;i<=maxn;i++){
        if(!bo[i]) { prime[++tot]=i; nxt[i]=tot; }
        for(int j=1;j<=tot&&prime[j]*i<=maxn;j++){
            bo[prime[j]*i]=1;
            nxt[prime[j]*i]=j;
            if(i%prime[j]==0) break;
        }        
    }
}
LL rongchi(LL yy){
    LL res=0;
    for(int i=1;i<(1<<pr[0]);i++){
        int flag=0,tmp=1;
        for(int j=0;j<pr[0];j++)
         if((1<<j)&i) flag++,tmp*=pr[j+1];
        if(flag&1) (res+=(LL)yy/tmp)%=mod;
        else ((res-=(LL)yy/tmp)+=mod)%=mod;
    }
    return ((LL)res+mod)%mod;
}
int main()
{
    //freopen("C.in","r",stdin);
    //freopen("C.out","w",stdout);
    scanf("%lld",&n);
    pre();
    nn=sqrt(n);
    for(int i=1;i<=nn;i++){
        pr[0]=0;
        xx=i;
        while(xx!=1){
            pr[++pr[0]]=prime[nxt[xx]];
            while(xx%pr[pr[0]]==0) 
            xx/=pr[pr[0]];
        }
        xx=i;
        ans+=((n/i-i-((rongchi(n/i)-rongchi(i))+mod)%mod)+mod)%mod;
    }
    ((ans*=2)+=1%mod)%=mod;
    printf("%lld",ans);
    return 0;
}
容斥原理 容斥简单题2.21
技术分享
//Twenty
#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<queue>
#include<vector>
const int maxn=110;
using namespace std;
double a[maxn][maxn];
int flag,n;
inline void read(double &x){
    char ch=getchar(); double f=1;
    while(ch!=-&&(ch<0||ch>9)) ch=getchar();
    if(ch==-) f=-1,ch=getchar();
    for(;ch>=0&&ch<=9;ch=getchar())  x=x*10+ch-0;
}
void work(){
    for(int i=1;i<=n;i++){
        int now=i;
        for(int j=i+1;j<=n;j++)
           if(fabs(a[j][i]>a[now][i])) now=j;
        if(now!=i)
           for(int j=i;j<=n+1;j++)
              swap(a[i][j],a[now][j]);
        if(a[i][i]==0) {flag=1;return;}
        for(int j=i+1;j<=n+1;j++)
           a[i][j]=a[i][j]/a[i][i];
        a[i][i]=1;
        for(int j=i+1;j<=n;j++){
           for(int k=i+1;k<=n+1;k++)
              a[j][k]-=a[i][k]*a[j][i];
              a[j][i]=0;
        }
    }
    for(int i=n;i>=1;i--)
       for(int j=i+1;j<=n;j++)
          a[i][n+1]-=a[i][j]*a[j][n+1];
}
int main()
{
   scanf("%d",&n);
   for(int i=1;i<=n;i++)
      for(int j=1;j<=n+1;j++)
          read(a[i][j]);
   work();
   if(flag) printf("No Solution\n");
   else {
   for(int i=1;i<=n;i++)
       printf("%.2lf\n",a[i][n+1]);
   }
   return 0;
}
高斯消元
技术分享
//Twenty
#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<queue>
#include<vector>
#include<complex>
#define pi acos(-1)
using namespace std;
const int maxn=2621450;
typedef complex<double> E;
E a[maxn],b[maxn];
int r[maxn],n,m,l;
void FFT(E *a,int f){
    for(int i=0;i<n;i++) if(i<r[i]) swap(a[i],a[r[i]]);
    for(int i=1;i<n;i<<=1){
        E wn(cos(pi/i),f*sin(pi/i));
        for(int p=i<<1,j=0;j<n;j+=p){
            E w(1,0);
            for(int k=0;k<i;k++,w*=wn){
                E x=a[j+k],y=w*a[j+k+i];
                a[j+k]=x+y; a[i+k+j]=x-y;
          }
        }
    }
}
inline int read(){
    int f=1,x=0;char ch;
    do{ch=getchar();if(ch==-)f=-1;}while(ch<0||ch>9);
    do{x=x*10+ch-0;ch=getchar();}while(ch>=0&&ch<=9);
    return f*x;
}
int main()
{
    n=read(); m=read();
    for(int i=0;i<=n;i++) a[i]=read();
    for(int i=0;i<=m;i++) b[i]=read();
    m+=n; for(n=1;n<=m;n<<=1) l++;
    for(int i=0;i<n;i++) r[i]=(r[i>>1]>>1)|((i&1)<<(l-1));
    FFT(a,1); FFT(b,1);
    for(int i=0;i<=n;i++) a[i]=a[i]*b[i];
    FFT(a,-1);
    for(int i=0;i<=m;i++) printf("%d ",(int)(a[i].real()/n+0.5)); 
    return 0;
}
FFT

 

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

VSCode自定义代码片段——.vue文件的模板

VSCode自定义代码片段1——vue主模板

VSCode自定义代码片段2——.vue文件的模板

VSCode自定义代码片段(vue主模板)

数论代码整理

Eclipse 中的通用代码片段或模板