CSP 2019 RP++

读入:(转自:chuyds's Blog

法一:

while(scanf("%d",&a)!=EOF)

法二:

while(cin>>n)

法三:

while(~scanf("%d",&a))

1.最小生成树

只会Kruskal w

#include<bits/stdc++.h>

using namespace std;

inline int read(){
    int ans=0;
    char last=' ',ch=getchar();
    while(ch>'9'||ch<'0') last=ch,ch=getchar();
    while(ch>='0'&&ch<='9') ans=(ans<<1)+(ans<<3)+ch-'0',ch=getchar();
    if(last=='-') ans=-ans;
    return ans;
}

int n,m;
int fa[5010];
struct node{
    int u,v,w;
}e[200010];

bool cmp(node a,node b) {
    return a.w<b.w;
}

int find(int x){
    if(fa[x]!=x) fa[x]=find(fa[x]);
    return fa[x];
}

int main(){
    n=read();
    m=read();
    for(int i=1;i<=m;i++) {
        e[i].u=read();
        e[i].v=read();
        e[i].w=read();
    }
    sort(e+1,e+m+1,cmp);
    int ans=0;
    for(int i=1;i<=n;i++) fa[i]=i;
    for(int i=1,u,v,fu,fv;i<=m;i++) {
        u=e[i].u;
        v=e[i].v;
        fu=find(u);
        fv=find(v);
        if(fu==fv) continue;
        fa[fu]=fv;
        ans+=e[i].w;
    }
    printf("%d",ans);
    return 0;
}

2.单源最短路

dijkstra

#include<bits/stdc++.h>
#define pa pair<int,int>

using namespace std;

inline int read(){
    int ans=0;
    char last=' ',ch=getchar();
    while(ch>'9'||ch<'0') last=ch,ch=getchar();
    while(ch>='0'&&ch<='9') ans=(ans<<1)+(ans<<3)+ch-'0',ch=getchar();
    if(last=='-') ans=-ans;
    return ans;
}
const int mxn=100010;

int n,m,s;
int head[mxn],ecnt;
struct node {
    int to,dis,nxt;
}e[mxn<<1];

void add(int from,int to,int dis){
    ++ecnt;
    e[ecnt].nxt=head[from];
    e[ecnt].to=to;
    e[ecnt].dis=dis;
    head[from]=ecnt;
}

int dis[mxn];
bool vis[mxn];
priority_queue<pa,vector<pa>,greater<pa> > q;
void dij(int s){
    dis[s]=0;
    q.push(make_pair(dis[s],s));
    while(!q.empty()){
        int u=q.top().second;
        q.pop();
        if(vis[u]) continue;
        vis[u]=1;
        for(int i=head[u],v;i;i=e[i].nxt){
            v=e[i].to;
            if(dis[v]>dis[u]+e[i].dis){
                dis[v]=dis[u]+e[i].dis;
                q.push(make_pair(dis[v],v));
            }
        }
    }
}

int main(){
    n=read();
    m=read();
    s=read();
    memset(dis,0x3f,sizeof(dis));
    for(int i=1,u,v,w;i<=m;i++){
        u=read();
        v=read();
        w=read();
        add(u,v,w);
    }
    dij(s);
    for(int i=1;i<=n;i++) printf("%d ",dis[i]);
    return 0;
}

spfa

#include<bits/stdc++.h>

using namespace std;

inline int read(){
    int ans=0;
    char last=' ',ch=getchar();
    while(ch>'9'||ch<'0') last=ch,ch=getchar();
    while(ch>='0'&&ch<='9') ans=(ans<<1)+(ans<<3)+ch-'0',ch=getchar();
    if(last=='-') ans=-ans;
    return ans;
}
const int mxn=100010;

int n,m,s;
int head[mxn],ecnt;
struct node {
    int to,dis,nxt;
}e[mxn<<3];

void add(int from,int to,int dis){
    ++ecnt;
    e[ecnt].nxt=head[from];
    e[ecnt].to=to;
    e[ecnt].dis=dis;
    head[from]=ecnt;
}
int dis[mxn];
bool vis[mxn];
queue<int> Q;

void spfa(){
    
    Q.push(s);
    for(int i=1;i<=n;i++) dis[i]=2147483647,vis[i]=0;
    vis[s]=1;dis[s]=0;
    while(!Q.empty()) {
        int u=Q.front();
        Q.pop();
        vis[u]=0;
        for(int i=head[u],v;i;i=e[i].nxt) {
            v=e[i].to;
            if(dis[v]>dis[u]+e[i].dis) {
                dis[v]=dis[u]+e[i].dis;
                if(!vis[v]) Q.push(v),vis[v]=1;
            }
        }
    }
}

int main(){
    n=read();
    m=read();
    s=read();
    
    for(int i=1,u,v,w;i<=m;i++){
        u=read();
        v=read();
        w=read();
        add(u,v,w);
    }
    spfa();
    for(int i=1;i<=n;i++) printf("%d ",dis[i]);
    return 0;
}

3.tarjan

void tarjan(int u) {
    dfn[u]=low[u]=++tim;
    vis[u]=1;
    s[top++]=u;
    for(int i=head[u],v;i;i=e[i].nxt) {
        v=e[i].to;
        if(!dfn[v]) {
            tarjan(v);
            low[u]=min(low[v],low[u]);
        } else 
            if(vis[v]) 
                low[u]=min(dfn[v],low[u]);
    }
    if(dfn[u]==low[u]){
        ++scc_cnt;
        while(s[top]!=u){
            top--;
            vis[s[top]]=0;
            scc[s[top]]=scc_cnt;
            cnt[scc_cnt]++;
        }
    }
}

4.kmp

扫描二维码关注公众号,回复: 7860834 查看本文章
#include<bits/stdc++.h>

using namespace std;

char a[mxn],b[mxn];
int lena,lenb;

int p[mxn];

void ych(){
    p[1]=0;
    int j=0;
    for(int i=1;i<lenb;i++) {
        while(j>0&&b[j+1]!=b[i+1]) j=p[j];
        if(b[j+1]==b[i+1]) j++;
        p[i+1]=j;
    }
}

void kmp(){
    int j=0;
    for(int i=0;i<lena;i++) {
        while(j>0&&b[j+1]!=a[i+1]) j=p[j];
        if(b[j+1]==a[i+1]) j++;
        if(j==lenb) {
            printf("%d\n",i+1-lenb+1);
            j=p[j];
        }
    }
}

int main(){
    scanf("%s%s",a+1,b+1);
    lena=strlen(a+1);
    lenb=strlen(b+1);
    ych();
    kmp();
    return 0;
}

trie树:

#include<bits/stdc++.h>

using namespace std;

int n,m,tot=1; 
char word[55];
int trie[500011][27];
int vis[500011];

void insert(char *s,int rt) {
    for(int i=0;i<strlen(s);i++) {
        int x=s[i]-'0';
        if(trie[rt][x]==0) trie[rt][x]=++tot;
        rt=trie[rt][x];
    }
    vis[rt]=1;
}

int search(char *s,int rt) {
    for(int i=0;i<strlen(s);i++) {
        int x=s[i]-'0';
        if(trie[rt][x]==0) return 0;
        rt=trie[rt][x];
    }
    if(vis[rt]==0) return 0;
    if(vis[rt]==1) { 
        vis[rt]=2;
        return 1;
    }
    if(vis[rt]==2)
        return 2;
}

int main() {
    scanf("%d",&n);
    for(int i=1;i<=n;i++) {
        scanf("%s",word);
        insert(word,1);
    }
    scanf("%d",&m);
    for(int i=1;i<=m;i++) {
        scanf("%s",word);
        int k=search(word,1);
        if(!k) printf("WRONG\n");
        else {
            if(k==1)    
                printf("OK\n");
            else 
                printf("REPEAT\n");
        }
    } 
    return 0;
}

5.线性筛

#include<bits/stdc++.h>

using namespace std;

const int mxn=100010;

int n;
bool is[mxn];
int pri[mxn],cnt;

int main(){
    scanf("%d",&n);
    for(int i=2;i<=n;i++) {
        if(!is[i]) pri[++cnt]=i;
        for(int j=1;j<=cnt&&pri[j]*i<=n;j++) {
            is[i*pri[j]]=1;
            if(i%pri[j]==0) break;
        }
    }
    for(int i=1;i<=cnt;i++) cout<<pri[i]<<" ";
    return 0;
}

6.求解同余方程:
\[ 求解:ax\equiv c(mod\ \ b)\\ ax=by+c\\ 即求解ax+by=c(正负无所谓\\ 若方程有解,则:\\ c=k\times gcd(a,b) \ \ k\in N^*\\ 扩展欧几里得定理求得的解为ax+by=exgcd(a,b)\\ 若要求解ax+by=k\times exgcd(a,b)\\在求解ax+by=exgcd(a,b)基础上,同乘k \\x,y的通解: x+=b/gcd(a,b),y-=a/gcd(a,b) \]

void exgcd(int a,int b,int &x,int &y) {
    if(b==0) {x=1;y=0;return a;}
    int g=exgcd(b,a%b,x,y);
    int t=x;
    x=y;
    y=t-a/b*x;
    return g;
}

7.中国剩余定理:

\(a_1,a_2 \cdots\cdots a_n\)是两两互质的正整数,\(M= \prod_{i=1}^na_i,M_i=M/a_i\)\(t_i\)是线性同余方程\(M_it_i≡1(\mod a_i)\)的一个解。对于任意的n个整数\(b_1,b_2 \cdots \cdots b_n\),则同余方程组:
\[ \begin{cases} x\equiv b_1 (\mod a_1)\\ x\equiv b_2 (\mod a_2)\\ x\equiv b_3 (\mod a_3)\\ ……\\ x\equiv b_n (\mod a_n)\\ \end{cases} \]

有整数解,方程组的解为\(x=b_1M_1t_1+b_2M_2t_2+ \cdots \cdots +b_nM_nt_n\).并且在%M意义下有唯一解

#include<bits/stdc++.h>
#define ll long long

using namespace std;

int n;
ll M,x,y,ans;
ll a[15],b[15];

ll exgcd(ll a,ll b,ll &x,ll &y) {
    if(b==0) {x=1;y=0;return a;};
    ll g=exgcd(b,a%b,x,y);
    ll t=x;
    x=y;
    y=t-a/b*x;
    return g;
}

void solve(int k) {
    ll M_=M/a[k];
    exgcd(M_,a[k],x,y);
    ans=(ans+((x*M_)%M*b[k])%M+M)%M;
}

int main() {
    scanf("%d",&n);
    M=1;
    for(int i=1;i<=n;i++) 
        scanf("%lld%lld",&a[i],&b[i]),M*=a[i];
    for(int i=1;i<=n;i++) 
        solve(i);
    printf("%lld",ans);
    return 0;
}

8.树状数组:

#include<bits/stdc++.h>
#define ll long long

using namespace std;

ll n,m;
ll c[1000000];

ll lowbit(ll x) { return x&(-x);}

void add(ll x,ll ad) {
    while(x<=n) {
        c[x]+=ad;
        x+=lowbit(x);
    }
}

ll sum(ll x) {
    ll S=0;
    while(x>0) {
        S+=c[x];
        x-=lowbit(x);
    }
    return S;
}

int main() {
     scanf("%lld%lld",&n,&m);
     for(int i=1,a;i<=n;i++) {
        scanf("%d",&a);
        add(i,a);
     }
     for(int i=1,opt,x,y;i<=m;i++) {
        scanf("%d%d%d",&opt,&x,&y);
        if(opt==1) 
            add(x,y);
        else 
            printf("%lld\n",sum(y)-sum(x-1));
     }
    return 0;
}

9.线段树:

#include<bits/stdc++.h>
#define ll long long

using namespace std;

const int mxn=100010;

int n,m;
ll a[mxn];
ll t[mxn<<2],tag[mxn<<2];

void build(int k,int l,int r) {
    if(l==r) {
        t[k]=a[l];
        return;
    }
    int mid=(l+r)>>1;
    build(k<<1,l,mid);
    build(k<<1|1,mid+1,r);
    t[k]=t[k<<1]+t[k<<1|1];
}

void pushdown(int k,int l,int r) {
    int mid=(l+r)>>1;
    if(!tag[k]) return;
    tag[k<<1]+=tag[k];
    tag[k<<1|1]+=tag[k];
    t[k<<1]+=(mid-l+1)*tag[k];
    t[k<<1|1]+=(r-mid)*tag[k];
    tag[k]=0;
}

void modify(int k,int l,int r,int x,int y,int q) {
    if(x<=l&&r<=y) {
        tag[k]+=q;
        t[k]+=(r-l+1)*q;
        return;
    }
    pushdown(k,l,r);
    int mid=(l+r)>>1;
    if(x<=mid) modify(k<<1,l,mid,x,y,q);
    if(y>mid) modify(k<<1|1,mid+1,r,x,y,q);
    t[k]=t[k<<1]+t[k<<1|1];
}

ll query(int k,int l,int r,int x,int y) {
    if(x<=l&&r<=y) 
        return t[k];
    pushdown(k,l,r);
    int mid=(l+r)>>1;
    ll rtn=0;
    if(x<=mid) rtn+=query(k<<1,l,mid,x,y);
    if(y>mid) rtn+=query(k<<1|1,mid+1,r,x,y);
    return rtn;
}

int main() {
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++) 
        scanf("%lld",&a[i]);
    build(1,1,n);
    for(int i=1,opt,x,y,k;i<=m;i++) {
        scanf("%d%d%d",&opt,&x,&y);
        if(opt==1) {
            scanf("%d",&k);
            modify(1,1,n,x,y,k);
        }
        else 
            printf("%lld\n",query(1,1,n,x,y));
    }
}

10.LCA:

(树剖

#include<bits/stdc++.h>

using namespace std;

const int mxn=500010;

int n,m,S;
struct node {
    int to,nxt;
}e[mxn<<1];
int ecnt,head[mxn];
void add(int from,int to) {
    ++ecnt;
    e[ecnt].to=to;
    e[ecnt].nxt=head[from];
    head[from]=ecnt;
}
int fa[mxn],siz[mxn],dep[mxn],son[mxn];
void dfs1(int u,int f) {
    fa[u]=f;
    siz[u]=1;
    dep[u]=dep[f]+1; 
    int maxn=-1;
    for(int i=head[u],v;i;i=e[i].nxt) {
        v=e[i].to;
        if(v==f) continue;
        dfs1(v,u);
        siz[u]+=siz[v];
        if(siz[v]>maxn) {
            maxn=siz[v];
            son[u]=v;
        }
    }
}
int top[mxn];
void dfs2(int u,int f) {
    if(son[f]==u) top[u]=top[f];
    else top[u]=u;
    if(son[u]) dfs2(son[u],u);
    for(int i=head[u],v;i;i=e[i].nxt) {
        v=e[i].to;
        if(v==f||v==son[u]) continue;
        dfs2(v,u);
    }
}

int getlca(int x,int y) {
    while(top[x]!=top[y]) {
        if(dep[top[x]]>dep[top[y]]) 
            x=fa[top[x]];
        else 
            y=fa[top[y]];
    }
    if(dep[x]>dep[y]) return y;
    else return x;
}

int main() {
    scanf("%d%d%d",&n,&m,&S);
    for(int i=1,x,y;i<n;i++) {
        scanf("%d%d",&x,&y);
        add(x,y);
        add(y,x);
    }
    dfs1(S,0);
    dfs2(S,0);
    for(int i=1,a,b,lca;i<=m;i++) {
        scanf("%d%d",&a,&b);
        lca=getlca(a,b);
        printf("%d\n",lca);
    }
    return 0;
}

倍增:

#include<bits/stdc++.h>

using namespace std;

const int mxn=500010;

int n,m,S;
struct node {
    int to,nxt;
}e[mxn<<1];
int ecnt,head[mxn];
void add(int from,int to) {
    ++ecnt;
    e[ecnt].to=to;
    e[ecnt].nxt=head[from];
    head[from]=ecnt;
}
int fa[mxn][20],dep[mxn];
void dfs(int u,int f) {
    fa[u][0]=f;
    for(int i=1;i<=19;i++)
        fa[u][i]=fa[fa[u][i-1]][i-1];
    dep[u]=dep[f]+1; 
    for(int i=head[u],v;i;i=e[i].nxt) {
        v=e[i].to;
        if(v==f) continue;
        dfs(v,u);
    }
}

int getlca(int x,int y) {
    if(dep[x]>dep[y]) swap(x,y);
    for(int i=19;i>=0;i--) 
        if(dep[fa[y][i]]>=dep[x]) 
            y=fa[y][i];
    if(x==y) return x;
    for(int i=19;i>=0;i--) {
        if(fa[x][i]!=fa[y][i]) {
            x=fa[x][i];
            y=fa[y][i];
        }
    }
    return fa[x][0];
}

int main() {
    scanf("%d%d%d",&n,&m,&S);
    for(int i=1,x,y;i<n;i++) {
        scanf("%d%d",&x,&y);
        add(x,y);
        add(y,x);
    }
    dfs(S,0);
    for(int i=1,x,y,lca;i<=m;i++) {
        scanf("%d%d",&x,&y);
        lca=getlca(x,y);
        printf("%d\n",lca);
    }
    return 0;
}

12.堆:

#include<bits/stdc++.h>
#define pa pair<int,int>
#define mk make_pair

using namespace std;

inline int read() {
    int ans=0;
    char last=' ',ch=getchar();
    while(ch>'9'||ch<'0') last=ch,ch=getchar();
    while(ch>='0'&&ch<='9') ans=(ans<<1)+(ans<<3)+ch-'0',ch=getchar();
    if(last=='-') ans=-ans;
    return ans; 
}

int n,siz;
int heap[1000080];

void insert(int x) {
    heap[++siz]=x;
    int nxt,now=siz;
    while(now>1) {
        nxt=now>>1;
        if(heap[nxt]<=heap[now]) break;
        swap(heap[now],heap[nxt]);
        now=nxt; 
    }
}

void Delete() {
    heap[1]=heap[siz--];
    int now=1,nxt;
    while((now<<1)<=siz) {
        nxt=now<<1;
        if(nxt<siz&&heap[nxt+1]<heap[nxt]) nxt++;
        if(heap[now]<=heap[nxt]) break;
        swap(heap[now],heap[nxt]);
        now=nxt;
    }
}

int main() {
    n=read();
    for(int i=1,opt,x;i<=n;i++) {
        opt=read();
        if(opt==1) {
            x=read();
            insert(x);
        }
        if(opt==2)
            printf("%d\n",heap[1]);
        if(opt==3)
            Delete(); 
    }
    return 0;
}

13.逆元:

定义:

\(ax\equiv 1(\mod b)\),且a与b互质,那么我们就能定义: x为a的逆元,记为\(a^{-1}\),所以我们也可以称 x 为 a 在 \(\mod b\) 意义下的倒数,

1.扩展欧几里得算法:

由逆元定义可知,求a在mod b意义下的逆元,就是求ax+by=1的解,因此我们可以使用扩欧算法:

int exgcd(int a,int b,int &x,int &y) {
    if(b==0){x=1;y=0;return a;}
    int g=exgcd(b,a%b,x,y);
    int t=x;
    x=y;
    y=t-a/b*x;
}

2.利用费马小定理或者欧拉定理

费马小定理:

如果 a,p 互质,那么 \(a^{p-1} ≡ 1 \ \ (mod \ p)\)

由此可以推出,\(a^{-1}=a^{p-2}\)

那么我们就可以用快速幂来完成求逆元的任务;

欧拉定理:

如果a,p互质,那么\(a^{\phi(p)} ≡ 1 \;(mod\; p)\),当 p 为质数时,\(\phi(p)=p-1\)

欧拉函数怎么求?

(只顺手写个快速幂行吧?)

ll quick_pow(int x,int k) {
    ll ans=1;
    while(k){
        if(k&1) ans=(ans*x)%mod;
        x=(x*x)%mod;
    }
    return ans;
}

3.线性递推(用于求解一段数的逆元
\[ 令p=ki+r;k=\left\lfloor\dfrac{p}{i}\right\rfloor,r=p\%i \ \ \ (i<p,k<p,r<i)\\ 则有:ki+r\equiv 0(mod \ p)①\\ ①式左右同乘i^{-1}\times r^{-1}得:\\ kr^{-1}+i^{-1}\equiv 0(mod \ p)\\ 移项得:i^{-1} \equiv -k*r^{-1} (mod\ p)  \\ 带入 k=\left\lfloor\dfrac{p}{i}\right\rfloor,r=p\%i\\   i^{-1}\equiv -\left\lfloor\dfrac{p}{i}\right\rfloor*(p\mod i)^{-1}(mod\ p)\\ 由于(p\mod i)<i\\ 因此在求出i^{-1}之前,我们已经求出(p\mod i)^{-1}\\ 用inv数组记录逆元 则:inv[i]=-\left\lfloor\dfrac{p}{i}\right\rfloor*inv[p\mod i] \mod p\\ 为了保证逆元>0,所以要在右边+p,即:inv[i]=-\left\lfloor\dfrac{p}{i}\right\rfloor*inv[p\mod i]+p \mod p\\ inv[1]=1;inv[0]=tan\frac{π}{2}设为0 \]

#include<bits/stdc++.h>
#define ll long long

using namespace std;

int n,p;
ll inv[3000010];

int main() {
    scanf("%d%d",&n,&p);
    inv[1]=1;
    puts("1");
    for(int i=2;i<=n;i++) {
        inv[i]=((-(p/i)*inv[p%i]+p)%p+p)%p;
        printf("%lld\n",inv[i]);
    }
    return 0;
}

14.矩阵加速:(模板
$$
a[1]=a[2]=a[3]=1;\

a[x]=a[x-1]+a[x-3] (a>3)
\[ 转移矩阵: \]
\begin{vmatrix}a_3\a_{2}\a_{1}\end{vmatrix}\times \begin{vmatrix}1&0&1\1&0&0\0&1&0\end{vmatrix}^{n-3}=\begin{vmatrix}a_{n}\a_{n-1}\a_{n-2}\end{vmatrix}
$$

15.高精度:

#include<bits/stdc++.h>

using namespace std;

char A[10090],B[10090];
int a[10090],b[10090],c[10090]; 

void sum() {
    scanf("%s",A);
    int lena=strlen(A);
    for(int i=0;i<lena;i++)
        a[lena-i]=A[i]-'0';
    scanf("%s",B);
    int lenb=strlen(B);
    for(int i=0;i<lenb;i++)
        b[lenb-i]=B[i]-'0';
    int len=max(lena,lenb);
    for(int i=1;i<=len;i++) {
        c[i]=a[i]+b[i];
    }
    for(int i=1;i<=len;i++) {
        c[i+1]+=(c[i]/10);
        c[i]%=10;
    }
    if(c[len+1]!=0) len++;
    for(int i=len;i>=1;i--)
        printf("%d",c[i]); 
}

void jian(){
        int bj=1;
    scanf("%s",A);
    scanf("%s",B);
    int lena=strlen(A);
    int lenb=strlen(B);
    if(lena<lenb) {
        bj=-1;
        swap(A,B);
        swap(lena,lenb);
    }
    if(lena==lenb&&strcmp(A,B)<0) {
        bj=-1;
        swap(A,B);
        swap(lena,lenb);
    }
    
    for(int i=0;i<lena;i++)
        a[lena-i]=A[i]-'0';
    
    
    for(int i=0;i<lenb;i++)
        b[lenb-i]=B[i]-'0';
    int len=max(lena,lenb);
    for(int i=1;i<=len;i++)
        c[i]=a[i]-b[i];
    for(int i=1;i<=len;i++) {
        if(c[i]<0) {
            c[i]+=10;
            c[i+1]--;
        }
    } 
    if(bj==-1) printf("-");
    while(c[len]==0&&len>1) len--;
    for(int i=len;i>=1;i--) 
        printf("%d",c[i]);
}

void Mul() {
    scanf("%s",A);
    int lena=strlen(A);
    for(int i=0;i<lena;i++)
        a[lena-i]=A[i]-'0';
    scanf("%s",B);
    int lenb=strlen(B);
    for(int i=0;i<lenb;i++)
        b[lenb-i]=B[i]-'0';
    for(int i=1;i<=lena;i++) 
        for(int j=1;j<=lenb;j++) 
            c[i+j-1]+=a[i]*b[j];
    for(int i=1;i<=lena+lenb-1;i++) {
        c[i+1]+=(c[i]/10);
        c[i]%=10;
    }
    int len=lena+lenb-1;
    while(c[len+1]>0) {
        c[len+2]+=(c[len+1]/10);
        c[len+1]%=10;
        len++;
    }
    for(int i=len;i>=1;i--)
        printf("%d",c[i]);
}

int main() {
    scanf("%s",A);
    int lena=strlen(A);
    for(int i=0;i<lena;i++)
        a[lena-i]=A[i]-'0';
    int B;
    scanf("%d",&B);
    for(int i=lena;i>=1;i--) {
        c[i]=a[i]/B;
        a[i-1]+=(a[i]%B)*10;
    }
    while(c[lena]==0&&lena>0) lena--;
    for(int i=lena;i>=1;i--)
        printf("%d",c[i]);
    return 0;
}

16.ST表:

#include<bits/stdc++.h>
 
using namespace std;

typedef long long ll;
typedef unsigned long long ull;
const int inf=2147483647;
inline ll read()
{
    char ch=getchar();
    ll x=0; 
    bool f=0;
    while(ch<'0'||ch>'9')
    {
        if(ch=='-') f=1;
        ch=getchar();
    }
    while(ch>='0'&&ch<='9')
    {
        x=(x<<3)+(x<<1)+(ch^48);
        ch=getchar();
    }
    return f?-x:x;
}
int n,m,a[1000009],st[1000009][23];
int lg[100009];
int qry(int l,int r)
{
    int qwq=log((double)(r-l+1))/log(2.0);
    return max(st[l][qwq],st[r-(1<<qwq)+1][qwq]);
}
int main()
{
    n=read();m=read();
    for(int i=1;i<=n;i++)
    {
        a[i]=read();
        st[i][0]=a[i];
    }
    for(int i=1;(1<<i)<=n;i++)
    {
        for(int j=1;j<=n;j++)
        {
            st[j][i]=max(st[j][i-1],st[j+(1<<(i-1))][i-1]);
        }
    }
    while(m--)
    {
        int l=read(),r=read();
        printf("%d\n",qry(l,r));
    }
}

17.高斯消元:

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<cstdlib>
using namespace std;
typedef long long ll;
typedef long double ld;
typedef pair<int,int> pr;
const double pi=acos(-1);
#define rep(i,a,n) for(int i=a;i<=n;i++)
#define per(i,n,a) for(int i=n;i>=a;i--)
#define Rep(i,u) for(int i=head[u];i;i=Next[i])
#define clr(a) memset(a,0,sizeof a)
#define pb push_back
#define mp make_pair
#define fi first
#define sc second
ld eps=1e-9;
ll pp=1000000007;
ll mo(ll a,ll pp){if(a>=0 && a<pp)return a;a%=pp;if(a<0)a+=pp;return a;}
ll powmod(ll a,ll b,ll pp){ll ans=1;for(;b;b>>=1,a=mo(a*a,pp))if(b&1)ans=mo(ans*a,pp);return ans;}
ll read(){
    ll ans=0;
    char last=' ',ch=getchar();
    while(ch<'0' || ch>'9')last=ch,ch=getchar();
    while(ch>='0' && ch<='9')ans=ans*10+ch-'0',ch=getchar();
    if(last=='-')ans=-ans;
    return ans;
}
//head(lh的代码头)
int n,m;
double a[100][100];

bool check(int k){
    if(fabs(a[k][n+1])<eps)return 1;// 如果小于0,返回1 
    for(int i=1;i<=n;i++) 
        if(fabs(a[k][i])>eps)return 1;//第k行的每个数都大于0 
    return 0;
}
int main(){
    n=read();m=read();//m*n的矩阵,
    // a_i,1 a_i,2 ... a_i,n a_i,n+1
    for(int i=1;i<=m;i++)
        for(int j=1;j<=n+1;j++)a[i][j]=read();//输入矩阵元素(因为除了这个m*n的矩阵,还要有一行答案qwq) (看洛谷题吧qwq) 
    for(int j=1;j<=m;j++){
            for(int k=1;k<=n+1;k++)cout<<a[j][k]<<" ";
            puts("");
        }//先把矩阵输出辽一遍 
    int flag=0;
    for(int i=1;i<=n;i++){
        int t=i;
        while(a[t][i]==0 && t<=n)t+=1;
        if(t==n+1){
            flag=1;
            continue;
        }//if判断是否有一行全为0,如果全为0 那么我们就少了至少1个方程,那么这个方程显然无唯一解 
        for(int j=1;j<=n+1;j++)swap(a[i][j],a[t][j]);//交换第i行和第t行的值,目的在于交换第i行和第t行后可以使a[1][1]!=0 
        double kk=a[i][i];//找到对角线qwq 
        for(int j=1;j<=n+1;j++)a[i][j]/=kk;//把这一行的每一项都除以对角线,使得对角线为1 
        for(int j=1;j<=m;j++) //这里真的要详细地讲一讲咯 
            if(i!=j){//首先i!=j这样就不再消对角线上的数了 
                double kk=a[j][i];//定义kk为第j行第i列的数 
                for(int k=1;k<=n+1;k++)//把每一项消成0qwq(先把第一列除了对角线全消为0然后第二第三……) 
                // 关于处理对角线这里以i=1,j=3做例子:当k=3时,a[3][3]-=a[3][1]*a[1][3]而这个时候a[3][1]已经为0,故对对角线无影响 
                    a[j][k]-=kk*a[i][k];
            }
        puts("------------");//画一个杠杠来分割每一次消元结果 
        for(int j=1;j<=m;j++){
            for(int k=1;k<=n+1;k++)cout<<a[j][k]<<" ";//输出每次消元结果 
            puts("");//输出空格 
        }
    }
    if(flag){//判断无解和多解的情况(上面已经提到了) 已经懵bi求救qwq 
        for(int i=1;i<=m;i++) 
            if(!check(i)){//利用check判断是无解还是多解  
                printf("No solution\n");
                return 0;
            }
            //每个答案行如果有一个等于0的数就多解??
        printf("So many solutions\n");
    }
}
-------------------------
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<cstdlib>
using namespace std;
long long read(){
    long long ans=0;
    char last=' ',ch=getchar();
    while(ch<'0' || ch>'9')last=ch,ch=getchar();
    while(ch>='0' && ch<='9')ans=ans*10+ch-'0',ch=getchar();
    if(last=='-')ans=-ans;
    return ans;
}
int n,m;
double a[100][100];

int main(){
    n=read();
    for(int i=1;i<=n;i++)
        for(int j=1;j<=n+1;j++)a[i][j]=read(); 
    int flag=0;
    for(int i=1;i<=n;i++){
        int t=i;
        while(a[t][i]==0 && t<=n)t+=1;
        if(t==n+1){
            flag=1;
            continue;
        }
        for(int j=1;j<=n+1;j++)swap(a[i][j],a[t][j]);
        double kk=a[i][i];
        for(int j=1;j<=n+1;j++)a[i][j]/=kk;
        for(int j=1;j<=n;j++) 
            if(i!=j){
                double kk=a[j][i];
                for(int k=1;k<=n+1;k++)
                    a[j][k]-=kk*a[i][k];
            }  
        }
    if(flag)printf("No Solution\n");
    else {for(int i=1;i<=n;i++)
         printf("%.2lf\n",a[i][n+1]);}
         return 0;
}
//和上面代码差不多的,只不过这个输出的是第n+1行,也就是每一个未知数的解(因为都消成1了qwq)

18.矩阵求逆:

#include<cstdio>
#include<iostream>
using namespace std;
typedef long long LL;
const int N=405;
int mod;
int n,m;
LL f[N][N<<1];//与下文相照应,这里N<<1指N/2,为了构造单位矩阵而乘的2 
LL r,ret;
LL ksm(LL u,LL v){ 
    ret=1;
    while(v){
        if(v&1)ret=ret*u%mod;
        u=u*u%mod;v>>=1;
    }
    return ret;
}
int main(){
    scanf("%d%d",&n,&mod);
    m=n*2; //乘2是为了后面建立一个单位矩阵 
    for(int i=1;i<=n;++i){
        for(int j=1;j<=n;j++)
            scanf("%lld",&f[i][j]);//输入n*n的矩阵 
        f[i][n+i]=1; //在 f后面又搞了一个单位矩阵qwq 
    }
    for(int i=1;i<=n;++i){ //高斯消元的板子
        for(int j=i;j<=n;j++)
            if(f[j][i]){
                for(int k=1;k<=m;k++)
                    swap(f[i][k],f[j][k]); 
                break;
            }
        if(!f[i][i]){
            puts("No Solution");
            return 0;
        } //判断是否有解(对角线为0) 
        r=ksm(f[i][i],mod-2); 
        for(int j=i;j<=m;++j) 
            f[i][j]=f[i][j]*r%mod;
        for(int j=1;j<=n;++j) 
            if(j!=i){
                r=f[j][i];
                for(int k=i;k<=m;++k)
                    f[j][k]=(f[j][k]-r*f[i][k]%mod+mod)%mod;
            }
}
    for(int i=1;i<=n;++i,puts(""))
        for(int j=n+1;j<=m;++j)
            printf("%lld ",f[i][j]);
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/zhuier-xquan/p/11864146.html