Lagrange 插值 & 高斯消元

Lagrange 插值 & 高斯消元

你说得对,高斯消元是后面补得,因为没啥可说的,放在一起吧。

你说得对,我是 sb,先学拉插再学高斯消元

拉插是用来进行多项式插值的有力工具。

统一设最后的函数为 g,点分别为 (x1,y1)...(xn,yn)

基础

  1. 普通拉插:

    考虑构造函数 f(i),使其满足:

    x=xj(j[1,n],ji),f(x)=0f(xi)=yi

    有构造:

    f(i)=yijixxjxixj

    比较显然。

    然后可以让 g(i)=f(i)=i=1nyijixxjxixj

    暴力实现是 O(n2) 的。

    可以优化到 O(nlog2n),挺麻烦,我不会,link

  2. 连续拉插:

    对于 x=[1,n]O(n) 拉插。

    将原式替换一下

    g(i)=i=1nyijixjij

    我们预处理出 xi 的前后缀积,分子就干完了。发现分母可以拆成 (i1)!×(ni)!×(1)ni,预处理阶乘逆元就行了。

  3. 重心拉插:

    可以让 O(n) 加新点感觉可以平替牛顿插值了

    将原式变换一下:

    g(i)=i=1nyijixxjxjxi=i=1n(xxi)i=1n(1xxi×i!=jyixixj)

    每次加点直接求 i!=jyixixj 即可。

    但是做题没用过。

  4. 求系数:

    直接模拟是 O(n3) 的,先吧 i=1n(xxi) 处理出来在模拟多项式除 xt 即可 O(n2)

有用定理:

Δf(i)=f(i)f(i1) 是一个 k 次多项式,则 fk 次多项式。

用法:

  1. 一个 会让 f 次数 +1
  2. 对于天然查分的 dp 可以设一个次数,用这个解出来,见最后一个题。

题目

  1. 一个人的数论:

    和莫反书接上回是吧。

    莫反,发现有 i=1nik,这是一个 k+1 次多项式,形如 i=1d+1cinic 是系数),将其带入在推即可,最后拉插求系数(也可以高斯消元)。

    CODE
    #include<bits/stdc++.h>
    #include<sys/mman.h>
    #include<fcntl.h>
    using namespace std;
    using llt=long long;
    using llf=long double;
    using ull=unsigned long long;
    #define Ct const
    #define Il __always_inline
    #define For(i,a,b,c) for(int i=(a);i<=(b);i+=(c))
    #define For_(i,a,b,c) for(int i=(a);i>=(b);i-=(c))
    #define For_it(i,a,b) for(auto i=(a);i!=(b);++i)
    namespace IO{
    #ifdef ONLINE_JUDGE
    int Fin=fileno(stdin); FILE* Fout=stdout;
    #elif defined(UN_FAST)
    FILE *Fin=freopen("in_out/in.in","r",stdin),*Fout=freopen("in_out/out.out","w",stdout);
    #else
    int Fin=open("in_out/in.in",0); FILE *Fout=freopen("in_out/out.out","w",stdout);
    #endif // file
    #ifdef UN_FAST
    char cc;
    #define G (cc=getchar())
    #define C cc
    #else
    const char *I=(char*)mmap(0,1<<28,1,2,Fin,0)-1;
    #define G (*++I)
    #define C (*I)
    #endif // fast (mmap)
    #define P(x) putc_unlocked(x,Fout)
    template<class T> Il void read(T &x){x=0;bool f=0; while(f|=G==45,C<48); while(x=x*10+(C&15),G>47); f?x=-x:0;}
    template<class T> void write(T x){if(x<0) P('-'),x=-x; if(x/10) write(x/10); P('0'+x%10);}
    Il void read(char &c){while(G<33); c=C;} void read(char *s){char *p=s-1; while(G<33); while(*++p=C,G>32); *++p='\0';}
    Il void read(string &s){s.clear(); while(G<33); while(s.push_back(C),G>32);}
    template<class T=int> Il T read(){T a; return read(a),a;}
    template<class T,class ...Argc> Il void read(T &x,Argc &...argc){read(x),read(argc...);}
    Il void write(const char &c){P(c);} Il void write(const char *s){for(const char *c=s;*c!='\0';++c) P(*c);}
    Il void write(const string &s){for(const char &c:s) P(c);}
    template<class T,class ...Argc> Il void write(const T &x,const Argc &...argc){write(x),write(argc...);}
    template<class T> Il void Write(const T &x){write(x),P(' ');} Il void Write(const char &c){P(c); if(c>32) P(' ');}
    template<class T,class ...Argc> Il void Write(const T &x,const Argc &...argc){Write(x),Write(argc...);}
    #undef G
    #undef C
    #undef P
    }using IO::read; using IO::write; using IO::Write;
    constexpr int W=1003,D=103,MOD=1e9+7;
    int d,w,n,ans,cp[W],ca[W];
    vector<int> ck;
    namespace MT{
    Il int Fpw(int a,int b){
    int ans=1;
    while(b){
    if(b&1) ans=1ll*ans*a%MOD;
    a=1ll*a*a%MOD,b>>=1;
    }
    return ans;
    }
    Il int Inv(Ct int &a){return Fpw(a,MOD-2);}
    class LGG{
    private:
    int cy[D];
    vector<int> tmp,mul;
    public:
    LGG(){tmp.reserve(D),mul.reserve(D);}
    Il void Gety(){For(i,1,d+2,1) cy[i]=(cy[i-1]+Fpw(i,d))%MOD;}
    Il void operator()(vector<int> &f){
    int len=d+2;
    f.clear(),f.resize(len),tmp.clear(),mul.clear(),mul.emplace_back(1);
    For(i,1,len,1){
    tmp.emplace_back(0); for(Ct int &k:mul) tmp.emplace_back(k);
    For(j,0,i-1,1) tmp[j]=(tmp[j]-1ll*mul[j]*i%MOD+MOD)%MOD;
    swap(tmp,mul),tmp.clear();
    }
    For(i,1,len,1){
    int fd=1; tmp.clear(),tmp.resize(len);
    For_(j,len,2,1) tmp[j-1]=(tmp[j-1]+mul[j])%MOD,tmp[j-2]=(tmp[j-2]+1ll*tmp[j-1]*i%MOD)%MOD;
    tmp[0]=(tmp[0]+mul[1])%MOD;
    For(j,1,len,1) if(i^j) fd=1ll*fd*(i-j)%MOD;
    fd=1ll*Inv((fd+MOD)%MOD)*cy[i]%MOD;
    For(j,0,len-1,1) f[j]=(f[j]+1ll*tmp[j]*fd%MOD)%MOD;
    }
    }
    }Lgg;
    }
    int main(){
    read(d,w); n=1;
    For(i,1,w,1) read(cp[i],ca[i]),n=1ll*n*MT::Fpw(cp[i],ca[i])%MOD;
    MT::Lgg.Gety(); MT::Lgg(ck);
    For(i,1,d+1,1){
    int tmp=1ll*ck[i]*MT::Fpw(n,i)%MOD;
    For(j,1,w,1) tmp=1ll*tmp*(1-MT::Fpw(cp[j],(d-i+MOD-1)%(MOD-1)))%MOD;
    ans=(ans+tmp)%MOD;
    }
    write((ans+MOD)%MOD);
    }
  2. 成绩比较

    拉插优化 dp。

    dpi,j 表示前 i 门课,有 j 个被碾压方案数。

    dpi,j=l=jkdpi1,l(jl)(nrijn1l)p=1uipnri(uip)ri1

    发现后面统计分数是一个 n 次多项式,直接拉插求值就可以避免枚举到 ui

    CODE
    #include<bits/stdc++.h>
    #include<sys/mman.h>
    #include<fcntl.h>
    using namespace std;
    using llt=long long;
    using llf=long double;
    using ull=unsigned long long;
    #define Ct const
    #define Il __always_inline
    #define For(i,a,b,c) for(int i=(a);i<=(b);i+=(c))
    #define For_(i,a,b,c) for(int i=(a);i>=(b);i-=(c))
    #define For_it(i,a,b) for(auto i=(a);i!=(b);++i)
    namespace IO{
    #ifdef ONLINE_JUDGE
    int Fin=fileno(stdin); FILE* Fout=stdout;
    #elif defined(UN_FAST)
    FILE *Fin=freopen("in_out/in.in","r",stdin),*Fout=freopen("in_out/out.out","w",stdout);
    #else
    int Fin=open("in_out/in.in",0); FILE *Fout=freopen("in_out/out.out","w",stdout);
    #endif // file
    #ifdef UN_FAST
    char cc;
    #define G (cc=getchar())
    #define C cc
    #else
    const char *I=(char*)mmap(0,1<<28,1,2,Fin,0)-1;
    #define G (*++I)
    #define C (*I)
    #endif // fast (mmap)
    #define P(x) putc_unlocked(x,Fout)
    template<class T> Il void read(T &x){x=0;bool f=0; while(f|=G==45,C<48); while(x=x*10+(C&15),G>47); f?x=-x:0;}
    template<class T> void write(T x){if(x<0) P('-'),x=-x; if(x/10) write(x/10); P('0'+x%10);}
    Il void read(char &c){while(G<33); c=C;} void read(char *s){char *p=s-1; while(G<33); while(*++p=C,G>32); *++p='\0';}
    Il void read(string &s){s.clear(); while(G<33); while(s.push_back(C),G>32);}
    template<class T=int> Il T read(){T a; return read(a),a;}
    template<class T,class ...Argc> Il void read(T &x,Argc &...argc){read(x),read(argc...);}
    Il void write(const char &c){P(c);} Il void write(const char *s){for(const char *c=s;*c!='\0';++c) P(*c);}
    Il void write(const string &s){for(const char &c:s) P(c);}
    template<class T,class ...Argc> Il void write(const T &x,const Argc &...argc){write(x),write(argc...);}
    template<class T> Il void Write(const T &x){write(x),P(' ');} Il void Write(const char &c){P(c); if(c>32) P(' ');}
    template<class T,class ...Argc> Il void Write(const T &x,const Argc &...argc){Write(x),Write(argc...);}
    #undef G
    #undef C
    #undef P
    }using IO::read; using IO::write; using IO::Write;
    const int N=103,MOD=1e9+7;
    int n,m,ck,u[N],cr[N],dp[N][N];
    namespace MT{
    int fac[N],ivf[N];
    Il int Fpw(int a,int b){
    int ans=1;
    while(b){
    if(b&1) ans=1ll*ans*a%MOD;
    b>>=1,a=1ll*a*a%MOD;
    }
    return ans;
    }
    Il int Inv(Ct int &a){return Fpw(a,MOD-2);}
    struct INIT{INIT(){
    fac[0]=1; For(i,1,N-3,1) fac[i]=1ll*fac[i-1]*i%MOD;
    ivf[N-3]=Inv(fac[N-3]);
    For_(i,N-3,1,1) ivf[i-1]=1ll*ivf[i]*i%MOD;
    }}Initer;
    Il int C(int a,int b){return (a<b||b<0)?0:1ll*fac[a]*ivf[b]%MOD*ivf[a-b]%MOD;}
    class LGG{
    private: int cy[N],lmul[N],rmul[N];
    public:
    Il void Gety(Ct int &r,Ct int &u){
    For(i,1,n+1,1) cy[i]=(cy[i-1]+1ll*Fpw(i,n-r)*Fpw(u-i,r-1)%MOD)%MOD;
    }
    Il int operator()(Ct int &x){
    int len=n+1,y=0;
    lmul[0]=1; For(i,1,len,1) lmul[i]=1ll*lmul[i-1]*(x-i)%MOD;
    rmul[len+1]=1; For_(i,len,1,1) rmul[i]=1ll*rmul[i+1]*(x-i)%MOD;
    For(i,1,len,1) y=(y+1ll*cy[i]*lmul[i-1]%MOD*rmul[i+1]%MOD*ivf[i-1]%MOD*ivf[len-i]%MOD*(len-i&1?-1:1)+MOD)%MOD;
    return y;
    }
    }Lgg;
    }
    int main(){
    read(n,m,ck);
    For(i,1,m,1) read(u[i]);
    For(i,1,m,1) read(cr[i]);
    dp[0][n-1]=1;
    For(i,1,m,1){
    MT::Lgg.Gety(cr[i],u[i]);
    int tmp=MT::Lgg(u[i]);
    For(j,ck,n-1,1) For(k,j,n-1,1)
    dp[i][j]=(dp[i][j]+1ll*dp[i-1][k]*MT::C(k,j)%MOD*MT::C(n-1-k,n-cr[i]-j)%MOD*tmp%MOD)%MOD;
    }
    write(dp[m][ck],'\n');
    }
  3. 教科书般的亵渎

    sb 题面描述,k 始终不变。

    式子显然,用拉插求 i=1nik 即可。

    CODE
    #include<bits/stdc++.h>
    #include<sys/mman.h>
    #include<fcntl.h>
    using namespace std;
    using llt=long long;
    using llf=long double;
    using ull=unsigned long long;
    #define Ct const
    #define Il __always_inline
    #define For(i,a,b,c) for(int i=(a);i<=(b);i+=(c))
    #define For_(i,a,b,c) for(int i=(a);i>=(b);i-=(c))
    #define For_it(i,a,b) for(auto i=(a);i!=(b);++i)
    namespace IO{
    #ifdef ONLINE_JUDGE
    int Fin=fileno(stdin); FILE* Fout=stdout;
    #elif defined(UN_FAST)
    FILE *Fin=freopen("in_out/in.in","r",stdin),*Fout=freopen("in_out/out.out","w",stdout);
    #else
    int Fin=open("in_out/in.in",0); FILE *Fout=freopen("in_out/out.out","w",stdout);
    #endif // file
    #ifdef UN_FAST
    char cc;
    #define G (cc=getchar())
    #define C cc
    #else
    const char *I=(char*)mmap(0,1<<28,1,2,Fin,0)-1;
    #define G (*++I)
    #define C (*I)
    #endif // fast (mmap)
    #define P(x) putc_unlocked(x,Fout)
    template<class T> Il void read(T &x){x=0;bool f=0; while(f|=G==45,C<48); while(x=x*10+(C&15),G>47); f?x=-x:0;}
    template<class T> void write(T x){if(x<0) P('-'),x=-x; if(x/10) write(x/10); P('0'+x%10);}
    Il void read(char &c){while(G<33); c=C;} void read(char *s){char *p=s-1; while(G<33); while(*++p=C,G>32); *++p='\0';}
    Il void read(string &s){s.clear(); while(G<33); while(s.push_back(C),G>32);}
    template<class T=int> Il T read(){T a; return read(a),a;}
    template<class T,class ...Argc> Il void read(T &x,Argc &...argc){read(x),read(argc...);}
    Il void write(const char &c){P(c);} Il void write(const char *s){for(const char *c=s;*c!='\0';++c) P(*c);}
    Il void write(const string &s){for(const char &c:s) P(c);}
    template<class T,class ...Argc> Il void write(const T &x,const Argc &...argc){write(x),write(argc...);}
    template<class T> Il void Write(const T &x){write(x),P(' ');} Il void Write(const char &c){P(c); if(c>32) P(' ');}
    template<class T,class ...Argc> Il void Write(const T &x,const Argc &...argc){Write(x),Write(argc...);}
    #undef G
    #undef C
    #undef P
    }using IO::read; using IO::write; using IO::Write;
    constexpr int M=55,MOD=1e9+7;
    int t,n,m,ca[M];
    namespace MT{
    Il int Fpw(int a,int b){
    int ans=1;
    while(b){
    if(b&1) ans=1ll*ans*a%MOD;
    b>>=1,a=1ll*a*a%MOD;
    }
    return ans;
    }
    Il int Inv(Ct int &a){return Fpw(a,MOD-2);}
    class LGG{
    private:
    int cy[M],lmul[M],rmul[M],fac[M],ivf[M];
    public:
    LGG(){
    fac[0]=1; For(i,1,M-3,1) fac[i]=1ll*fac[i-1]*i%MOD;
    ivf[M-3]=Inv(fac[M-3]);
    For_(i,M-3,1,1) ivf[i-1]=1ll*ivf[i]*i%MOD;
    }
    Il void Gety(){int k=m+1; For(i,1,k+2,1) cy[i]=(cy[i-1]+Fpw(i,k))%MOD;}
    Il int operator()(Ct int &x){
    int len=m+3,y=0;
    lmul[0]=1; For(i,1,len,1) lmul[i]=1ll*lmul[i-1]*(x-i)%MOD;
    rmul[len+1]=1; For_(i,len,1,1) rmul[i]=1ll*rmul[i+1]*(x-i)%MOD;
    For(i,1,len,1) y=(y+1ll*cy[i]*lmul[i-1]%MOD*rmul[i+1]%MOD*ivf[i-1]%MOD*ivf[len-i]%MOD*(len-i&1?-1:1)+MOD)%MOD;
    return y;
    }
    }Lgg;
    }
    int main(){
    read(t);
    while(t--){
    read(n,m); MT::Lgg.Gety();
    For(i,1,m,1) read(ca[i]); ca[0]=0;
    sort(ca,ca+m+1);
    int ans=0;
    For(i,0,m,1){
    ans=(ans+MT::Lgg(n-ca[i]))%MOD;
    For(j,i+1,m,1) ans=(ans-MT::Fpw(ca[j]-ca[i],m+1)+MOD)%MOD;
    }
    write(ans,'\n');
    }
    }
  4. tyvj 1858 XLkxc

    奇妙题目。

    拉插套拉插,由有用定理(见上)可知,其是一个 k+3 次多项式,因为其中有 a+id 太大,无法直接求,需要提前插出后面函数。

    CODE
    #include<bits/stdc++.h>
    #include<sys/mman.h>
    #include<fcntl.h>
    using namespace std;
    using llt=long long;
    using llf=long double;
    using ull=unsigned long long;
    #define Ct const
    #define Il __always_inline
    #define For(i,a,b,c) for(int i=(a);i<=(b);i+=(c))
    #define For_(i,a,b,c) for(int i=(a);i>=(b);i-=(c))
    #define For_it(i,a,b) for(auto i=(a);i!=(b);++i)
    #define int long long
    namespace IO{
    #ifdef ONLINE_JUDGE
    int Fin=fileno(stdin); FILE* Fout=stdout;
    #elif defined(UN_FAST)
    FILE *Fin=freopen("in_out/in.in","r",stdin),*Fout=freopen("in_out/out.out","w",stdout);
    #else
    int Fin=open("in_out/in.in",0); FILE *Fout=freopen("in_out/out.out","w",stdout);
    #endif // file
    #ifdef UN_FAST
    char cc;
    #define G (cc=getchar())
    #define C cc
    #else
    const char *I=(char*)mmap(0,1<<28,1,2,Fin,0)-1;
    #define G (*++I)
    #define C (*I)
    #endif // fast (mmap)
    #define P(x) putc_unlocked(x,Fout)
    template<class T> Il void read(T &x){x=0;bool f=0; while(f|=G==45,C<48); while(x=x*10+(C&15),G>47); f?x=-x:0;}
    template<class T> void write(T x){if(x<0) P('-'),x=-x; if(x/10) write(x/10); P('0'+x%10);}
    Il void read(char &c){while(G<33); c=C;} void read(char *s){char *p=s-1; while(G<33); while(*++p=C,G>32); *++p='\0';}
    Il void read(string &s){s.clear(); while(G<33); while(s.push_back(C),G>32);}
    template<class T=int> Il T read(){T a; return read(a),a;}
    template<class T,class ...Argc> Il void read(T &x,Argc &...argc){read(x),read(argc...);}
    Il void write(const char &c){P(c);} Il void write(const char *s){for(const char *c=s;*c!='\0';++c) P(*c);}
    Il void write(const string &s){for(const char &c:s) P(c);}
    template<class T,class ...Argc> Il void write(const T &x,const Argc &...argc){write(x),write(argc...);}
    template<class T> Il void Write(const T &x){write(x),P(' ');} Il void Write(const char &c){P(c); if(c>32) P(' ');}
    template<class T,class ...Argc> Il void Write(const T &x,const Argc &...argc){Write(x),Write(argc...);}
    #undef G
    #undef C
    #undef P
    }using IO::read; using IO::write; using IO::Write;
    constexpr int K=150,MOD=1234567891;
    int t,k,ca,n,d;
    namespace MT{
    int fac[K],ivf[K];
    Il int Fpw(int a,int b){
    int ans=1;
    while(b){
    if(b&1) ans=1ll*ans*a%MOD;
    b>>=1,a=1ll*a*a%MOD;
    }
    return ans;
    }
    Il int Inv(Ct int &a){return Fpw(a,MOD-2);}
    struct INIT{INIT(){
    fac[0]=1; For(i,1,K-3,1) fac[i]=1ll*fac[i-1]*i%MOD;
    ivf[K-3]=Inv(fac[K-3]);
    For_(i,K-3,1,1) ivf[i-1]=1ll*ivf[i]*i%MOD;
    }}Initer;
    class LGG{
    private:
    int cy[K],lmul[K],rmul[K];
    public:
    Il int &Y(Ct int &x){return cy[x];}
    Il int operator()(Ct int &x,Ct int &len){
    int y=0;
    lmul[0]=1; For(i,1,len,1) lmul[i]=1ll*lmul[i-1]*(x-i)%MOD;
    rmul[len+1]=1; For_(i,len,1,1) rmul[i]=1ll*rmul[i+1]*(x-i)%MOD;
    For(i,1,len,1) y=(y+1ll*cy[i]*lmul[i-1]%MOD*rmul[i+1]%MOD*ivf[i-1]%MOD*ivf[len-i]%MOD*(len-i&1?-1:1)+MOD)%MOD;
    return y;
    }
    }La,Lb;
    Il void Init(){
    int pw[K]={0}; For(i,1,k+3,1) pw[i]=Fpw(i,k);
    For(i,1,k+3,1){
    Lb.Y(i)=0;
    For(j,1,i,1) Lb.Y(i)=(Lb.Y(i)+1ll*(i-j+1)*pw[j]%MOD)%MOD;
    }
    La.Y(0)=Lb(ca,k+3); For(i,1,k+4,1) La.Y(i)=(La.Y(i-1)+Lb((ca+i*d)%MOD,k+3))%MOD;
    }
    }
    signed main(){
    read(t);
    while(t--){
    read(k,ca,n,d);
    MT::Init();
    write(MT::La(n,k+4),'\n');
    }
    }
  5. calc

    另一种拉插优化 dp。

    dpi,j 表示值域到 i,选 j 个方案数,枚举第 i 个选不选,有。

    dpi,j=dpi1,j1×i×j+dpi1,j

    发现它天然差分,有:

    dpi,jdpi1,j=dpi1,j1×i×j

    dpi,j 是关于 itj 次多项式,有:

    tj1=tj1+1

    显然 t 是等差序列,有 tn=2n

    所以只求 2n+1 项即可。

    CODE
    #include<bits/stdc++.h>
    #include<sys/mman.h>
    #include<fcntl.h>
    using namespace std;
    using llt=long long;
    using llf=long double;
    using ull=unsigned long long;
    #define Ct const
    #define Il __always_inline
    #define For(i,a,b,c) for(int i=(a);i<=(b);i+=(c))
    #define For_(i,a,b,c) for(int i=(a);i>=(b);i-=(c))
    #define For_it(i,a,b) for(auto i=(a);i!=(b);++i)
    namespace IO{
    #ifdef ONLINE_JUDGE
    int Fin=fileno(stdin); FILE* Fout=stdout;
    #elif defined(UN_FAST)
    FILE *Fin=freopen("in_out/in.in","r",stdin),*Fout=freopen("in_out/out.out","w",stdout);
    #else
    int Fin=open("in_out/in.in",0); FILE *Fout=freopen("in_out/out.out","w",stdout);
    #endif // file
    #ifdef UN_FAST
    char cc;
    #define G (cc=getchar())
    #define C cc
    #else
    const char *I=(char*)mmap(0,1<<28,1,2,Fin,0)-1;
    #define G (*++I)
    #define C (*I)
    #endif // fast (mmap)
    #define P(x) putc_unlocked(x,Fout)
    template<class T> Il void read(T &x){x=0;bool f=0; while(f|=G==45,C<48); while(x=x*10+(C&15),G>47); f?x=-x:0;}
    template<class T> void write(T x){if(x<0) P('-'),x=-x; if(x/10) write(x/10); P('0'+x%10);}
    Il void read(char &c){while(G<33); c=C;} void read(char *s){char *p=s-1; while(G<33); while(*++p=C,G>32); *++p='\0';}
    Il void read(string &s){s.clear(); while(G<33); while(s.push_back(C),G>32);}
    template<class T=int> Il T read(){T a; return read(a),a;}
    template<class T,class ...Argc> Il void read(T &x,Argc &...argc){read(x),read(argc...);}
    Il void write(const char &c){P(c);} Il void write(const char *s){for(const char *c=s;*c!='\0';++c) P(*c);}
    Il void write(const string &s){for(const char &c:s) P(c);}
    template<class T,class ...Argc> Il void write(const T &x,const Argc &...argc){write(x),write(argc...);}
    template<class T> Il void Write(const T &x){write(x),P(' ');} Il void Write(const char &c){P(c); if(c>32) P(' ');}
    template<class T,class ...Argc> Il void Write(const T &x,const Argc &...argc){Write(x),Write(argc...);}
    #undef G
    #undef C
    #undef P
    }using IO::read; using IO::write; using IO::Write;
    constexpr int N=1010;
    int MOD,dp[N][N],n,ca;
    namespace MT{
    int fac[N],ivf[N];
    Il int Fpw(int a,int b){
    int ans=1;
    while(b){
    if(b&1) ans=1ll*ans*a%MOD;
    b>>=1,a=1ll*a*a%MOD;
    }
    return ans;
    }
    Il int Inv(Ct int &a){return Fpw(a,MOD-2);}
    Il void Init(){
    fac[0]=1; For(i,1,N-3,1) fac[i]=1ll*fac[i-1]*i%MOD;
    ivf[N-3]=Inv(fac[N-3]);
    For_(i,N-3,1,1) ivf[i-1]=1ll*ivf[i]*i%MOD;
    }
    class LGG{
    private: int cy[N],lmul[N],rmul[N];
    public:
    Il int &Y(Ct int &i){return cy[i];}
    Il int operator()(Ct int &x,Ct int &len){
    int y=0;
    lmul[0]=1; For(i,1,len,1) lmul[i]=1ll*lmul[i-1]*(x-i)%MOD;
    rmul[len+1]=1; For_(i,len,1,1) rmul[i]=1ll*rmul[i+1]*(x-i)%MOD;
    For(i,1,len,1) y=(y+1ll*cy[i]*lmul[i-1]%MOD*rmul[i+1]%MOD*ivf[i-1]%MOD*ivf[len-i]%MOD*(len-i&1?-1:1)+MOD)%MOD;
    return y;
    }
    }Lgg;
    }
    int main(){
    read(ca,n,MOD);
    MT::Init();
    int m=n*2+1;
    For(i,0,m,1) dp[i][0]=1;
    For(i,1,m,1) For(j,1,n,1) dp[i][j]=(1ll*dp[i-1][j-1]*i*j%MOD+dp[i-1][j])%MOD;
    For(i,1,m,1) MT::Lgg.Y(i)=dp[i][n];
    write(MT::Lgg(ca,m));
    }

高斯消元

其实真正的高斯消元没啥用,真正用的多的都是高斯约旦了。

高斯约旦分别判无解和自由元:

每次新消元时从一开始选,因为可以选之前因为是 0 而跳过的,注意一下优先级,具体见代码十分压行

CODE
Il int Gss(double a[N][N]){
For(i,1,n,1){
int nw=i; For(j,1/*not i*/,n,1) if((i<=j||Isz(a[j][j])/*judge it not used*/)&&fabs(a[j][i])>fabs(a[nw][i])) nw=j;
if(Isz(a[nw][i])) continue; swap(a[i],a[nw]);
For(j,1,n,1) if(i^j){double tmp=a[j][i]/a[i][i]; For(k,i,n+1,1) a[j][k]-=tmp*a[i][k];}
}
int fg=1; For(i,1,n,1) Isz(a[i][i])?fg=-(!Isz(a[i][n+1])||fg==-1/*priority!!*/):a[i][n+1]/=a[i][i]; return fg;
}

题都是板子。

  1. 线性方程组

    真·板子。

    CODE
    #include<bits/stdc++.h>
    #include<sys/mman.h>
    #include<fcntl.h>
    using namespace std;
    using llt=long long;
    using llf=long double;
    using ull=unsigned long long;
    #define Ct const
    #define Il __always_inline
    #define For(i,a,b,c) for(int i=(a);i<=(b);i+=(c))
    #define For_(i,a,b,c) for(int i=(a);i>=(b);i-=(c))
    #define For_it(i,a,b) for(auto i=(a);i!=(b);++i)
    namespace IO{
    #ifdef ONLINE_JUDGE
    int Fin=fileno(stdin); FILE* Fout=stdout;
    #elif defined(UN_FAST)
    FILE *Fin=freopen("in_out/in.in","r",stdin),*Fout=freopen("in_out/out.out","w",stdout);
    #else
    int Fin=open("in_out/in.in",0); FILE *Fout=freopen("in_out/out.out","w",stdout);
    #endif // file
    #ifdef UN_FAST
    char cc;
    #define G (cc=getchar())
    #define C cc
    #else
    const char *I=(char*)mmap(0,1<<28,1,2,Fin,0)-1;
    #define G (*++I)
    #define C (*I)
    #endif // fast (mmap)
    #define P(x) putc_unlocked(x,Fout)
    template<class T> Il void read(T &x){x=0;bool f=0; while(f|=G==45,C<48); while(x=x*10+(C&15),G>47); f?x=-x:0;}
    template<class T> void write(T x){if(x<0) P('-'),x=-x; if(x/10) write(x/10); P('0'+x%10);}
    Il void read(char &c){while(G<33); c=C;} void read(char *s){char *p=s-1; while(G<33); while(*++p=C,G>32); *++p='\0';}
    Il void read(string &s){s.clear(); while(G<33); while(s.push_back(C),G>32);}
    template<class T=int> Il T read(){T a; return read(a),a;}
    template<class T,class ...Argc> Il void read(T &x,Argc &...argc){read(x),read(argc...);}
    Il void write(const char &c){P(c);} Il void write(const char *s){for(const char *c=s;*c!='\0';++c) P(*c);}
    Il void write(const string &s){for(const char &c:s) P(c);}
    template<class T,class ...Argc> Il void write(const T &x,const Argc &...argc){write(x),write(argc...);}
    template<class T> Il void Write(const T &x){write(x),P(' ');} Il void Write(const char &c){P(c); if(c>32) P(' ');}
    template<class T,class ...Argc> Il void Write(const T &x,const Argc &...argc){Write(x),Write(argc...);}
    #undef G
    #undef C
    #undef P
    }using IO::read; using IO::write; using IO::Write;
    constexpr int N=103;
    constexpr double eps=1e-7;
    int n; double c[N][N];
    Il bool Isz(Ct double f){return fabs(f)<eps;}
    Il int Gss(double a[N][N]){
    For(i,1,n,1){
    int nw=i; For(j,1,n,1) if((i<=j||Isz(a[j][j]))&&fabs(a[j][i])>fabs(a[nw][i])) nw=j;
    if(Isz(a[nw][i])) continue; swap(a[i],a[nw]);
    For(j,1,n,1) if(i^j){double tmp=a[j][i]/a[i][i]; For(k,i,n+1,1) a[j][k]-=tmp*a[i][k];}
    }
    int fg=1; For(i,1,n,1) Isz(a[i][i])?fg=-(!Isz(a[i][n+1])||fg==-1):a[i][n+1]/=a[i][i]; return fg;
    }
    int main(){
    read(n);
    For(i,1,n,1) For(j,1,n+1,1) c[i][j]=read<int>();
    int ans=Gss(c);
    if(ans<=0) write(ans,'\n');
    else For(i,1,n,1) Isz(c[i][n+1])?printf("x%d=0\n",i):printf("x%d=%.2lf\n",i,c[i][n+1]);
    }
  2. 球形空间产生器sphere

    题意模拟有 n+1 个二次方程。

    发现给了 n+1 个,直接差分消去二次项,就变成 n 个一次方程。

    CODE
    #include<bits/stdc++.h>
    #include<sys/mman.h>
    #include<fcntl.h>
    using namespace std;
    using llt=long long;
    using llf=long double;
    using ull=unsigned long long;
    #define Ct const
    #define Il __always_inline
    #define For(i,a,b,c) for(int i=(a);i<=(b);i+=(c))
    #define For_(i,a,b,c) for(int i=(a);i>=(b);i-=(c))
    #define For_it(i,a,b) for(auto i=(a);i!=(b);++i)
    #define UN_FAST
    namespace IO{
    #ifdef ONLINE_JUDGE
    int Fin=fileno(stdin); FILE* Fout=stdout;
    #elif defined(UN_FAST)
    FILE *Fin=freopen("in_out/in.in","r",stdin),*Fout=freopen("in_out/out.out","w",stdout);
    #else
    int Fin=open("in_out/in.in",0); FILE *Fout=freopen("in_out/out.out","w",stdout);
    #endif // file
    #ifdef UN_FAST
    char cc;
    #define G (cc=getchar())
    #define C cc
    #else
    const char *I=(char*)mmap(0,1<<28,1,2,Fin,0)-1;
    #define G (*++I)
    #define C (*I)
    #endif // fast (mmap)
    #define P(x) putc_unlocked(x,Fout)
    template<class T> Il void read(T &x){x=0;bool f=0; while(f|=G==45,C<48); while(x=x*10+(C&15),G>47); f?x=-x:0;}
    template<class T> void write(T x){if(x<0) P('-'),x=-x; if(x/10) write(x/10); P('0'+x%10);}
    Il void read(char &c){while(G<33); c=C;} void read(char *s){char *p=s-1; while(G<33); while(*++p=C,G>32); *++p='\0';}
    Il void read(string &s){s.clear(); while(G<33); while(s.push_back(C),G>32);}
    template<class T=int> Il T read(){T a; return read(a),a;}
    template<class T,class ...Argc> Il void read(T &x,Argc &...argc){read(x),read(argc...);}
    Il void write(const char &c){P(c);} Il void write(const char *s){for(const char *c=s;*c!='\0';++c) P(*c);}
    Il void write(const string &s){for(const char &c:s) P(c);}
    template<class T,class ...Argc> Il void write(const T &x,const Argc &...argc){write(x),write(argc...);}
    template<class T> Il void Write(const T &x){write(x),P(' ');} Il void Write(const char &c){P(c); if(c>32) P(' ');}
    template<class T,class ...Argc> Il void Write(const T &x,const Argc &...argc){Write(x),Write(argc...);}
    #undef G
    #undef C
    #undef P
    }using IO::read; using IO::write; using IO::Write;
    constexpr int N=13;
    constexpr double eps=1e-7;
    int n;
    double cpos[N][N],c[N][N];
    namespace MT{
    Il bool Isz(Ct double f){return fabs(f)<eps;}
    Il void Gss(double a[N][N]){
    For(i,1,n,1){
    int nw=i; For(j,i+1,n,1) if(fabs(a[j][i])>fabs(a[nw][i])) nw=j; swap(a[i],a[nw]);
    For(j,1,n,1) if(i^j){double tmp=a[j][i]/a[i][i]; For(k,i,n+1,1) a[j][k]-=tmp*a[i][k];}
    } For(i,1,n,1) a[i][n+1]/=a[i][i];
    }
    }
    int main(){
    read(n);
    For(i,1,n+1,1) For(j,1,n,1) scanf("%lf",&cpos[i][j]);
    For(i,1,n,1){
    double tmp=0;
    For(j,1,n,1) c[i][j]=2*(cpos[i+1][j]-cpos[i][j]),tmp+=cpos[i+1][j]*cpos[i+1][j]-cpos[i][j]*cpos[i][j];
    c[i][n+1]=tmp;
    }
    MT::Gss(c);
    For(i,1,n,1) printf("%.3f ",c[i][n+1]);
    }
  3. 臭气弹

    考虑类似 dp 的转移,考虑从其他点转移来的概率,设概率,解方程,注意起点加一。

    CODE
    #include<bits/stdc++.h>
    #include<sys/mman.h>
    #include<fcntl.h>
    using namespace std;
    using llt=long long;
    using llf=long double;
    using ull=unsigned long long;
    #define Ct const
    #define Il __always_inline
    #define For(i,a,b,c) for(int i=(a);i<=(b);i+=(c))
    #define For_(i,a,b,c) for(int i=(a);i>=(b);i-=(c))
    #define For_it(i,a,b) for(auto i=(a);i!=(b);++i)
    namespace IO{
    #ifdef ONLINE_JUDGE
    int Fin=fileno(stdin); FILE* Fout=stdout;
    #elif defined(UN_FAST)
    FILE *Fin=freopen("in_out/in.in","r",stdin),*Fout=freopen("in_out/out.out","w",stdout);
    #else
    int Fin=open("in_out/in.in",0); FILE *Fout=freopen("in_out/out.out","w",stdout);
    #endif // file
    #ifdef UN_FAST
    char cc;
    #define G (cc=getchar())
    #define C cc
    #else
    const char *I=(char*)mmap(0,1<<28,1,2,Fin,0)-1;
    #define G (*++I)
    #define C (*I)
    #endif // fast (mmap)
    #define P(x) putc_unlocked(x,Fout)
    template<class T> Il void read(T &x){x=0;bool f=0; while(f|=G==45,C<48); while(x=x*10+(C&15),G>47); f?x=-x:0;}
    template<class T> void write(T x){if(x<0) P('-'),x=-x; if(x/10) write(x/10); P('0'+x%10);}
    Il void read(char &c){while(G<33); c=C;} void read(char *s){char *p=s-1; while(G<33); while(*++p=C,G>32); *++p='\0';}
    Il void read(string &s){s.clear(); while(G<33); while(s.push_back(C),G>32);}
    template<class T=int> Il T read(){T a; return read(a),a;}
    template<class T,class ...Argc> Il void read(T &x,Argc &...argc){read(x),read(argc...);}
    Il void write(const char &c){P(c);} Il void write(const char *s){for(const char *c=s;*c!='\0';++c) P(*c);}
    Il void write(const string &s){for(const char &c:s) P(c);}
    template<class T,class ...Argc> Il void write(const T &x,const Argc &...argc){write(x),write(argc...);}
    template<class T> Il void Write(const T &x){write(x),P(' ');} Il void Write(const char &c){P(c); if(c>32) P(' ');}
    template<class T,class ...Argc> Il void Write(const T &x,const Argc &...argc){Write(x),Write(argc...);}
    #undef G
    #undef C
    #undef P
    }using IO::read; using IO::write; using IO::Write;
    constexpr int N=303;
    constexpr double eps=1e-7;
    int n,m,gph[N][N],dgr[N];
    double cpos[N][N],c[N][N],p,q;
    namespace MT{
    Il bool Isz(Ct double f){return fabs(f)<eps;}
    Il void Gss(double a[N][N]){
    For(i,1,n,1){
    int nw=i; For(j,i+1,n,1) if(fabs(a[j][i])>fabs(a[nw][i])) nw=j; swap(a[i],a[nw]);
    For(j,1,n,1) if(i^j){double tmp=a[j][i]/a[i][i]; For(k,i,n+1,1) a[j][k]-=tmp*a[i][k];}
    } For(i,1,n,1) a[i][n+1]/=a[i][i];
    }
    }
    int main(){
    read(n,m); p=read<int>(),q=read<int>();
    For(i,1,m,1){
    int u,v; read(u,v);
    gph[u][v]=gph[v][u]=1,++dgr[u],++dgr[v];
    }
    For(i,1,n,1){
    c[i][i]=-1;
    For(j,1,n,1) if(gph[i][j]) c[i][j]=(q-p)/q/dgr[j];
    } c[1][n+1]=-1;
    MT::Gss(c);
    For(i,1,n,1) printf("%.6lf\n",c[i][n+1]*p/q);
    }
  4. 开关问题

    设每个开关状态,容易列出异或方程。

    统计个数就是 2自由元个数 因为每个自由元有两个状态(这个卡了我好久,我是 sb)。

    CODE
    #include<bits/stdc++.h>
    #include<sys/mman.h>
    #include<fcntl.h>
    using namespace std;
    using llt=long long;
    using llf=long double;
    using ull=unsigned long long;
    #define Ct const
    #define Il __always_inline
    #define For(i,a,b,c) for(int i=(a);i<=(b);i+=(c))
    #define For_(i,a,b,c) for(int i=(a);i>=(b);i-=(c))
    #define For_it(i,a,b) for(auto i=(a);i!=(b);++i)
    namespace IO{
    #ifdef ONLINE_JUDGE
    int Fin=fileno(stdin); FILE* Fout=stdout;
    #elif defined(UN_FAST)
    FILE *Fin=freopen("in_out/in.in","r",stdin),*Fout=freopen("in_out/out.out","w",stdout);
    #else
    int Fin=open("in_out/in.in",0); FILE *Fout=freopen("in_out/out.out","w",stdout);
    #endif // file
    #ifdef UN_FAST
    char cc;
    #define G (cc=getchar())
    #define C cc
    #else
    const char *I=(char*)mmap(0,1<<28,1,2,Fin,0)-1;
    #define G (*++I)
    #define C (*I)
    #endif // fast (mmap)
    #define P(x) putc_unlocked(x,Fout)
    template<class T> Il void read(T &x){x=0;bool f=0; while(f|=G==45,C<48); while(x=x*10+(C&15),G>47); f?x=-x:0;}
    template<class T> void write(T x){if(x<0) P('-'),x=-x; if(x/10) write(x/10); P('0'+x%10);}
    Il void read(char &c){while(G<33); c=C;} void read(char *s){char *p=s-1; while(G<33); while(*++p=C,G>32); *++p='\0';}
    Il void read(string &s){s.clear(); while(G<33); while(s.push_back(C),G>32);}
    template<class T=int> Il T read(){T a; return read(a),a;}
    template<class T,class ...Argc> Il void read(T &x,Argc &...argc){read(x),read(argc...);}
    Il void write(const char &c){P(c);} Il void write(const char *s){for(const char *c=s;*c!='\0';++c) P(*c);}
    Il void write(const string &s){for(const char &c:s) P(c);}
    template<class T,class ...Argc> Il void write(const T &x,const Argc &...argc){write(x),write(argc...);}
    template<class T> Il void Write(const T &x){write(x),P(' ');} Il void Write(const char &c){P(c); if(c>32) P(' ');}
    template<class T,class ...Argc> Il void Write(const T &x,const Argc &...argc){Write(x),Write(argc...);}
    #undef G
    #undef C
    #undef P
    }using IO::read; using IO::write; using IO::Write;
    constexpr int N=303;
    int t,n;
    bool c[N][N],bg[N];
    Il int Gss(bool a[N][N]){
    For(i,1,n,1){
    int nw; For(j,1,n,1) if((i<=j||!a[j][j])&&a[j][i]) nw=j;
    if(!a[nw][i]) continue; swap(a[i],a[nw]);
    For(j,1,n,1) if(i^j&&a[j][i]) For(k,i,n+1,1) a[j][k]^=a[i][k];
    }
    int tmp=0; For(i,1,n,1) if(!a[i][i]){if(a[i][n+1]) tmp=-1; else if(tmp!=-1) ++tmp;} return tmp;
    }
    int main(){
    read(t);
    while(t--){
    read(n); memset(c,0,sizeof(c));
    For(i,1,n,1) c[i][i]=1,read(bg[i]);
    For(i,1,n,1) c[i][n+1]=read()^bg[i];
    int u,v; while(read(v,u),u||v) c[u][v]=1;
    int ans=Gss(c);
    if(ans==-1) write("Oh,it's impossible~!!\n");
    else write((llt)pow(2,ans),'\n');
    }
    }

带状矩阵

这就不能约旦了,有交换行和交换列两种做法。

交换列的要维护当前元的编号,交换行的有二倍常数(因为最多会让这一行长度乘二),并且在只有一半带状时没法做。

全部带状 nd2,一半带状 n2d

posted @   5k_sync_closer  阅读(11)  评论(0编辑  收藏  举报
编辑推荐:
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
阅读排行:
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
点击右上角即可分享
微信分享提示