省选模拟25

今天这个出奇的简单,于是我250分,第一又AK了

第一题,考场上看了一眼就知道是后缀自动机,然而空间不够用了

第二题,一眼切了,直接线段树维护矩阵乘

第三题,只会一个\(\mathcal{O(n^3logn)}\)的做法,还有一点点结论没有观察出来...

T1 前缀

前缀,前缀,KMP不就是找最长border的??直接把每一个前缀的border个数加起来就是答案了

AC_code
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define fo(i,x,y) for(int i=(x);i<=(y);i++)
#define fu(i,x,y) for(int i=(x);i>=(y);i--)
int read(){
    int s=0,t=1;char ch=getchar();
    while(!isdigit(ch)){if(ch=='-')t=-1;ch=getchar();}
    while(isdigit(ch)){s=s*10+ch-'0';ch=getchar();}
    return s*t;
}
const int N=1e7+5;
char a[N];
int n,nxt[N],sum[N];
ll ans;
signed main(){
    freopen("pre.in","r",stdin);
    freopen("pre.out","w",stdout);
    // cerr<<(sizeof(sam)>>20)<<endl;
    scanf("%s",a+1);n=strlen(a+1);sum[1]=ans=1;
    for(int i=2,j=0;i<=n;i++){
        while(a[i]!=a[j+1]&&j)j=nxt[j];
        if(a[i]==a[j+1])j++;nxt[i]=j;
        sum[i]=sum[j]+1;ans+=sum[i];
        //cerr<<sum[i]<<endl;
    }
    printf("%lld",ans);
    return 0;
}

T2 斐波那契

好用的矩阵乘...

AC_code
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define fo(i,x,y) for(int i=(x);i<=(y);i++)
#define fu(i,x,y) for(int i=(x);i>=(y);i--)
int read(){
    int s=0,t=1;char ch=getchar();
    while(!isdigit(ch)){if(ch=='-')t=-1;ch=getchar();}
    while(isdigit(ch)){s=s*10+ch-'0';ch=getchar();}
    return s*t;
}
const int N=1e5+5;
const int mod=1004535809;
int ksm(int x,int y){
    int ret=1;
    while(y){
        if(y&1)ret=ret*x%mod;
        x=x*x%mod;y>>=1;
    }return ret;
}
struct matrix{
    int x[2][2];
    matrix(){memset(x,0,sizeof(x));}
    matrix operator + (matrix a)const{
        matrix ret;
        fo(i,0,1)fo(j,0,1)ret.x[i][j]=(x[i][j]+a.x[i][j])%mod;
        return ret;
    }
    matrix operator * (matrix a)const{
        matrix ret;
        fo(i,0,1)fo(k,0,1)if(x[i][k])fo(j,0,1)ret.x[i][j]=(ret.x[i][j]+x[i][k]*a.x[k][j])%mod;
        return ret;
    }
    bool operator == (matrix a)const{
        fo(i,0,1)fo(j,0,1)if(x[i][j]!=a.x[i][j])return false;
        return true;
    }
    bool operator !=(matrix a)const{
        return !(*this==a);
    }
    void print(){
        fo(i,0,1){
            fo(j,0,1)printf("%lld ",x[i][j]);
            printf("\n");
        }printf("\n");
    }
}xs,oe,now;
matrix mksm(matrix x,int y){
    matrix ret;
    fo(i,0,1)ret.x[i][i]=1;
    while(y){
        if(y&1)ret=ret*x;
        x=x*x;y>>=1;
    }return ret;
}
int n,m,a[N];
struct XDS{
    #define ls x<<1
    #define rs x<<1|1
    matrix sum[N*4],tag[N*4];
    void pushup(int x){
        sum[x]=sum[ls]+sum[rs];
        return ;
    }
    void pushdown(int x){
        sum[ls]=sum[ls]*tag[x];
        tag[ls]=tag[ls]*tag[x];
        sum[rs]=sum[rs]*tag[x];
        tag[rs]=tag[rs]*tag[x];
        tag[x]=oe;
    }
    void build(int x,int l,int r){
        tag[x]=oe;
        if(l==r){
            sum[x]=mksm(xs,a[l]-1);
            return ;
        }
        int mid=l+r>>1;
        build(ls,l,mid);build(rs,mid+1,r);
        pushup(x);return ;
    }
    void ins(int x,int l,int r,int ql,int qr,int v){
        if(ql<=l&&r<=qr){
            sum[x]=sum[x]*now;
            tag[x]=tag[x]*now;
            return ;
        }
        int mid=l+r>>1;if(tag[x]!=oe)pushdown(x);
        if(ql<=mid)ins(ls,l,mid,ql,qr,v);
        if(qr>mid)ins(rs,mid+1,r,ql,qr,v);
        pushup(x);return ;
    }
    int query(int x,int l,int r,int ql,int qr){
        if(ql<=l&&r<=qr)return sum[x].x[0][0];
        int mid=l+r>>1,ret=0;if(tag[x]!=oe)pushdown(x);
        if(ql<=mid)ret=(ret+query(ls,l,mid,ql,qr))%mod;
        if(qr>mid)ret=(ret+query(rs,mid+1,r,ql,qr))%mod;
        pushup(x);return ret;
    }
    #undef ls
    #undef rs
}xds;
signed main(){
    freopen("fib.in","r",stdin);
    freopen("fib.out","w",stdout);
    xs.x[0][0]=xs.x[0][1]=xs.x[1][0]=1;
    oe.x[0][0]=oe.x[1][1]=1;
    n=read();m=read();
    fo(i,1,n)a[i]=read();
    xds.build(1,1,n);
    while(m--){
        int tp=read(),l=read(),r=read(),x;
        if(tp==1){
            x=read();now=mksm(xs,x);
            xds.ins(1,1,n,l,r,x);
        }
        else {
            printf("%lld\n",xds.query(1,1,n,l,r));
        }
    }
    return 0;
}

T3 过路费

枚举最小的计入贡献的是那条边,然后把所有边的权值都减去这条边的权值

最后加上一个k*这条边的权值

可以证明这样的话,对于不合法的情况都会算多!

AC_code
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define fo(i,x,y) for(int i=(x);i<=(y);i++)
#define fu(i,x,y) for(int i=(x);i>=(y);i--)
int read(){
    int s=0,t=1;char ch=getchar();
    while(!isdigit(ch)){if(ch=='-')t=-1;ch=getchar();}
    while(isdigit(ch)){s=s*10+ch-'0';ch=getchar();}
    return s*t;
}
const int N=1005;
const int M=2005;
const int inf=0x3f3f3f3f3f3f3f3f;
int n,m,k,s,t,ans=inf;
struct D{int x,y,w;}d[M];
bool comd(D a,D b){return a.w<b.w;}
struct E{int to,nxt,val;}e[M];
int head[N],rp;
void add_edg(int x,int y,int z){
    e[++rp].to=y;e[rp].nxt=head[x];
    e[rp].val=z;head[x]=rp;
}
int dis[N];bool vis[N];
struct node{
    int x,ds;
    bool operator < (node a)const{
        return ds>a.ds;
    }
};
priority_queue<node> q;
void spfa(int lim){
    memset(dis,0x3f,sizeof(dis));
    memset(vis,false,sizeof(vis));
    dis[s]=0;q.push(node{s,0});
    while(!q.empty()){
        int x=q.top().x;q.pop();
        if(vis[x])continue;vis[x]=true;
        for(int i=head[x];i;i=e[i].nxt){
            int y=e[i].to;
            if(dis[x]+e[i].val>=dis[y])continue;
            dis[y]=dis[x]+e[i].val;
            q.push(node{y,dis[y]});
        }
    }
    if(lim==1)ans=min(ans,dis[t]);
    else ans=min(ans,dis[t]+k*d[lim].w);
}
signed main(){
    freopen("fee.in","r",stdin);
    freopen("fee.out","w",stdout);
    memset(dis,0x3f,sizeof(dis));
    n=read();m=read();k=read();s=read();t=read();
    fo(i,1,m)d[i].x=read(),d[i].y=read(),d[i].w=read();
    if(k==0){printf("0");return 0;}
    sort(d+1,d+m+1,comd);
    memset(head,0,sizeof(head));rp=0;
    fo(j,1,m)add_edg(d[j].x,d[j].y,d[j].w);
    spfa(1);
    fo(i,2,m-k+1){
        memset(head,0,sizeof(head));rp=0;
        fo(j,1,i-1)add_edg(d[j].x,d[j].y,0);
        fo(j,i,m)add_edg(d[j].x,d[j].y,d[j].w-d[i].w);
        spfa(i);
    }
    printf("%lld",ans);
    return 0;
}
posted @ 2022-03-04 15:17  fengwu2005  阅读(48)  评论(0编辑  收藏  举报