数论&&快排&&dp板子

板子日DAY2

逆元

线性递推求逆元

一个易懂的证明

ll inv[30000529];
int main()
{
    ll n=read(),p=read();
    inv[1]=1;
    for(int i=2;i<=n;i++){
        inv[i]=(p-p/i)*inv[p%i]%p;
    } 
    for(int i=1;i<=n;i++){
        cout<"\n";
    }
    return 0;
}

小费马

注意满足 ap1=1(modp) 的条件为gcd(a,p)=1

ll fast_pow(int a,int p)
{
    ll ans=1; 
    for(;p;p>>=1,a=(a*a)%MOD){
        if(p&1)
        {
            ans=(ans*a)%MOD;
        }
    }
    return ans;
}
int main()
{
    //ios::sync_with_stdio(false);
    int n=read(),p=read();
    MOD=p;
    for(int i=1;i<=n;i++)
    cout<2)<<"\n";
    return 0;
}

线性阶乘+小费马求逆元

数论&&快排&&dp板子_第1张图片
转自luogu 感谢作者:积累

int MOD; 
long long  fast_pow(long long a,int p)
{
    long long ans=1; 
    for(;p;p>>=1,a=(a*a)%MOD){
        if(p&1)
        {
            ans=(ans*a)%MOD;
        }
    }
    return ans;
}
long long  a[3000001],f[3000001],g[3000001];
int main()
{
    //ios::sync_with_stdio(false);
    int n=read(),p=read();
    MOD=p;
    f[0]=1;
    for(int i=1;i<=n;i++){
        f[i]=(f[i-1]*i)%MOD;
    }
    g[n]=fast_pow(f[n],p-2);
    for(int i=n-1;i>=1;i--){
        g[i]=(g[i+1]*(i+1))%MOD;
    }
    for(int i=1;i<=n;i++){
        cout<<(g[i]*f[i-1]%MOD)<<"\n";
    }
    return 0;
}

扩展欧几里得(证明在这里)

ll exgcd(int a,int b,int &x,int &y){
    if(b==0){
        x=1;
        y=0;
        return a;
    }
    else {
        exgcd(b,a%b,y,x);
        /** int t=x;
        x=y;
        y=(t-a/b*y);*/
        y-=(a/b)*x;
    }
}
int main()
{
    //ios::sync_with_stdio(false);      
    int a=read(),b=read(),x,y;
    exgcd(a,b,x,y); 
    while(x<=0){
        x+=b;
    }cout<return 0;
}

中国剩余定理

(模数互素)

证明在这里

ll a[1000],m[1000];
void exgcd(ll a,ll b,ll &x,ll &y){
    if(b==0){
        x=1,y=0;return ;
    }
    else {
        exgcd(b,a%b,y,x);
        y-=a/b*x;
    }
}
int main()
{
    //ios::sync_with_stdio(false);
    ll n=read(),x=read(),y=read();
    for(ll i=1;i<=n;i++){
        m[i]=read(),a[i]=read();
    }
    ll M=1;
    for(ll i=1;i<=n;i++){
        M*=m[i];
    }
    ll ans=0;
    for(ll i=1;i<=n;i++){
        ll mi=M/m[i];
        ll x,y;
        exgcd(mi,m[i],x,y);x+=m[i];
        ans=(ans+a[i]*mi*x)%M;
        ans%=M;
    }

线性筛素数

(详见传送门)

    notprime[1]=notprime[0]=1;
    for(int i=2;i<=n;i++){
        if(!notprime[i]){
            prime[++cnt]=i;
        }
        for(int j=1;j<=cnt&&prime[j]*i<=n;j++){
            notprime[prime[j]*i]=1;
            if(prime[j]%i==0)break;
        }
    }

矩阵加速

(左横右竖)

const int MOD= 1e9+7;
struct matrix{
    int n,m;
    ll a[200][200];
    matrix operator *(matrix &b) {       //别忘&!!! 
        matrix ans;
        if(b.n!=n)cout<<"error";
        ans.n=n,ans.m=b.m;
        for(int i=1;i<=n;i++){
            for(int j=1;j<=m;j++){
                ans.a[i][j]=0;
            }
        }                        ///别忘初始化!!! 
        for(int i=1;i<=n;i++){
            for(int j=1;j<=b.m;j++){
                for(int k=1;k<=m;k++){
                    ans.a[i][j]+=(a[i][k]*b.a[k][j])%MOD;
                    ans.a[i][j]%=MOD;
                }
            }
        }
        return ans;
    }
    void show(){
        for(int i=1;i<=n;i++){
            for(int j=1;j<=m;j++){
                cout<" ";
            }cout<<"\n";
        }
    }
};
matrix fast_pow(matrix &a,ll p){  ///这个引用很玄学 不带可能会崩
    matrix ans;
    ans=a;
    for(int i=1;i<=a.n;i++){
        for(int j=1;j<=a.m;j++){
            if(i==j)ans.a[i][j]=1;
            else  ans.a[i][j]=0;    
        }
    }
    for(;p;p>>=1,a=a*a){
        if(p&1) ans=ans*a;
    }

    return ans;
}

Lucas定理

ll f[maxn],MOD;
ll fast_pow(ll a,ll p){
    ll ans=1;
    for(;p;p>>=1,a=a*a%MOD){
        if(p&1){
            ans*=a;
            ans%=MOD;
        }
    }
    return ans;
}
ll C(ll n, ll m){
    if(mreturn 0;
    return f[m]*fast_pow((f[m-n]*f[n])%MOD,MOD-2)%MOD; 
}
ll lucas(ll n,ll m){
    if(n==0) return 1;
    else return (C(n%MOD,m%MOD)*lucas(n/MOD,m/MOD))%MOD;
}
int main()
{
    //ios::sync_with_stdio(false);
    int T=read();
    while(T--){
        ll n=read(),m=read();MOD=read();
        f[0]=1;
        for(int i=1;i<=MOD;i++){
            f[i]=f[i-1]*i%MOD;
        }
        cout<"\n"; 
    }
    return 0;
}

快排

void qsort(int l,int r){
    if(l>=r)return;
    srand(time(NULL));
    int k=rand()%(r-l+1)+l;
    swap(a[l],a[k]);
    int i=l,j=r;
    int sd=a[l];
    while(iwhile(i=sd)--j;
        a[i]=a[j];
        while(i1,r);
    return;
}

最长公共子序列

(特解&&标解)

const int maxn=100100;
int mmp[maxn],g[maxn],cnt,a[maxn],b[maxn],dp[1001][1001];
void solve1(int n){
    for(int i=1;i<=n;i++){
        int a=read();
        mmp[a]=i;
    }
    for(int i=1;i<=n;i++){
        int a=read();
        int b=mmp[a];
        if(b>g[cnt]){
            g[++cnt]=b;
        }
        else {
            int l=1,r=cnt,mid;
            while(l<=r){
                mid=l+r>>1;
                if(g[mid]>b){
                    r=mid-1;      //二分别写反了!!
                }else l=mid+1;
            }
            if(l!=0)g[l]=b;
            //*upper_bound(g+1,g+cnt+1,b)=b;
        }
    }
    cout<
}
void solve2(int n){
    for(int i=1;i<=n;i++){
        a[i]=read();
    }
    for(int i=1;i<=n;i++){
        b[i]=read();
    }
    for(int i=1;i<=n;i++){
        for(int j=1;j<=n;j++){
            if(a[i]==b[j]){
                dp[i][j]=dp[i-1][j-1]+1;
            }
            else {
                dp[i][j]=max(dp[i-1][j],dp[i][j-1]);
            }
        }
    }
    cout<
}
int main()
{
    //ios::sync_with_stdio(false);
    int n=read();
    if(n<=1000)solve2(n);
    else solve1(n);
    return 0;
}

你可能感兴趣的:(NOIP)