省选模拟29

不得不说这题吧有点意思,想半天想不出来,直到要放弃的时候灵光一现!!

第一题,上来干了一个小时,不会,要弃了,后来回头发现就是个dp,我用bfs实现的!

第二题,一路从\(n^3\)\(n^2\)再到不会了,发现了只有\(\mathcal{O(n)}\)个区间,但是不会快速求值......

第三题,看见期望就跑路了

T1 卷王

直接倒序dp,状态就是亮灭的状态,记录所有的值,输出就好了

AC_code
#include<bits/stdc++.h>
using namespace std;
#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<<3)+(s<<1)+(ch^48);ch=getchar();}
    return s*t;
}
const int N=1<<17;
const int inf=0x3f3f3f3f;
int T,n;char ch[20];
int val[20][20],all,len;
int dis[N];bool vis[N];
queue<int> q;
signed main(){
    freopen("roll.in","r",stdin);
    freopen("roll.out","w",stdout);
    T=read();
    fo(i,0,15){
        fo(j,1,i+1)val[i][j]=val[i][j-1]|(1<<i-j+1);
        fo(j,i+2,16)val[i][j]=val[i][j-1];
    }
    memset(dis,0x3f,sizeof(dis));
    q.push(0);dis[0]=0;vis[0]=true;
    while(!q.empty()){
        int x=q.front();q.pop();vis[x]=false;
        fo(i,0,15){
            int now=x^val[i][dis[x]+1];
            if(dis[now]>dis[x]+1){
                dis[now]=dis[x]+1;
                if(!vis[now])q.push(now),vis[now]=true;
            }
            fo(j,dis[x]+2,i+1){
                now=x^val[i][j];
                if(dis[now]>j){
                    dis[now]=j;
                    if(!vis[now])q.push(now),vis[now]=true;
                }
            }
        }
    }
    while(T--){
        scanf("%s",ch+1);all=0;len=strlen(ch+1);
        fo(i,1,len)all=(all<<1)+(ch[i]^48);
        int ret=dis[all];
        if(ret==-1)printf("QwQ\n");
        else printf("%d\n",ret);
    }
    return 0;
}

T2 赢王

有贡献的区间一定是在序列上前缀和同余的作为端点

而这样的最小区间的数量事是线性的,直接计算每个区间的答案乘上系数即可,考场上死在了不知道怎么快速计算

快速计算的话,我使用的是主席树

我们发现这个取min操作是从中间分开的,那么我们就可以记录某一个范围内的数的个数和它的和

这样我们分类讨论,毕竟函数值只有两种嘛,好像还挺麻烦的??

AC_code
#include<bits/stdc++.h>
using namespace std;
#define ll long long
// #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<<3)+(s<<1)+(ch^48);ch=getchar();}
    return s*t;
}
const int N=1e6+5;
const int mod=998244353;
// const ll inf=0x3f3f3f3f3f3f3f3f;
int n,k,a[N],pre[N];ll ans;
int lsh[N],lh;
struct ZXS{
    struct POT{int ls,rs,siz;ll sum;}tr[N*21];
    int seg,rt[N];
    void pushup(int x){
        tr[x].sum=tr[tr[x].ls].sum+tr[tr[x].rs].sum;
        tr[x].siz=tr[tr[x].ls].siz+tr[tr[x].rs].siz;
        return ;
    }
    void ins(int &x,int px,int l,int r,int pos,int v){
        x=++seg;tr[x]=tr[px];
        if(l==r)return tr[x].siz++,tr[x].sum+=v,void();
        int mid=l+r>>1;
        if(pos<=mid)ins(tr[x].ls,tr[px].ls,l,mid,pos,v);
        else ins(tr[x].rs,tr[px].rs,mid+1,r,pos,v);
        pushup(x);return ;
    }
    int sz;ll sm;
    void query(int x,int y,int l,int r,int ql,int qr){
        if(!x||ql>qr)return ;
        if(ql<=l&&r<=qr){
            sz+=tr[x].siz-tr[y].siz;
            sm+=tr[x].sum-tr[y].sum;
            return ;
        }
        int mid=l+r>>1;
        if(ql<=mid)query(tr[x].ls,tr[y].ls,l,mid,ql,qr);
        if(qr>mid)query(tr[x].rs,tr[y].rs,mid+1,r,ql,qr);
        return ;
    }
    ll que(int lim,int s,int t,int l,int r,int tp=0){
        // cerr<<lim<<" "<<s<<" "<<t<<" "<<l<<" "<<r<<" "<<tp<<endl;
        int ql,qr;ll ret=0,res=0;
        if(l<lim){sz=sm=0;
            ql=lower_bound(lsh+1,lsh+lh+1,l)-lsh;
            qr=upper_bound(lsh+1,lsh+lh+1,min(lim-1,r))-lsh-1;
            query(rt[t],rt[s-1],1,lh,ql,qr);
            ret+=1ll*sz*k+sm-1ll*sz*lim;res+=sz;
        }
        if(r>lim){sz=sm=0;
            ql=lower_bound(lsh+1,lsh+lh+1,max(lim+1,l))-lsh;
            qr=upper_bound(lsh+1,lsh+lh+1,r)-lsh-1;
            query(rt[t],rt[s-1],1,lh,ql,qr);
            ret+=sm-1ll*sz*lim;res+=sz;
        }
        if(tp)ret=1ll*res*k-ret;
        return ret;
    }
    ll qry(int l,int r){ll ret=0;
        // fo(i,l,r)ret+=min((pre[i]-pre[l-1]+k)%k,k-(pre[i]-pre[l-1]+k)%k);
        // return ret;
        int ql=pre[l-1],qr=(pre[l-1]+(k>>1))%k;
        if(ql<=qr)ret+=que(pre[l-1],l,r,ql,qr);
        else {
            ret+=que(pre[l-1],l,r,ql,k-1);
            ret+=que(pre[l-1],l,r,0,qr);
        }
        ql=(pre[l-1]+(k>>1)+1)%k;qr=(pre[l-1]+k-1)%k;
        // cerr<<ql<<" "<<qr<<endl;
        if(ql<=qr)ret+=que(pre[l-1],l,r,ql,qr,1);
        else {
            ret+=que(pre[l-1],l,r,ql,k-1,1);
            ret+=que(pre[l-1],l,r,0,qr,1);
        }
        return ret;
    }
}zxs;
int buc[N],nxt[N],fro[N];
bool vis[N];
signed main(){
    freopen("win.in","r",stdin);
    freopen("win.out","w",stdout);
    // cerr<<(sizeof(zxs)>>20)<<endl;
    n=read();k=read();
    fo(i,1,n){
        a[i]=read();
        pre[i]=(pre[i-1]+a[i])%k;
        lsh[++lh]=pre[i];
    }lsh[++lh]=0;
    sort(lsh+1,lsh+lh+1);
    lh=unique(lsh+1,lsh+lh+1)-lsh-1;
    memset(buc,-1,sizeof(buc));
    buc[lower_bound(lsh+1,lsh+lh+1,0)-lsh]=0;
    fo(i,1,n){
        int pos=lower_bound(lsh+1,lsh+lh+1,pre[i])-lsh;
        zxs.ins(zxs.rt[i],zxs.rt[i-1],1,lh,pos,pre[i]);
        if(~buc[pos])nxt[buc[pos]]=i,fro[i]=buc[pos];
        buc[pos]=i;
    }
    // cerr<<zxs.qry(1,2)<<endl;
    ans=(ans-1ll*n*(n+1)/2%mod+mod)%mod;
    // cerr<<ans<<endl;
    fo(i,0,n)if(!vis[i]){
        int now=i,all=1;vis[now]=true;
        while(nxt[now])vis[nxt[now]]=true,now=nxt[now],all++;
        now=nxt[i];int cnt=0,las=i;
        // cerr<<all<<endl;
        ans=(ans+1ll*all*(all-1)/2%mod)%mod;
        while(now){cnt++;
            // cerr<<las<<" "<<now<<" "<<cnt<<" "<<(all-cnt)<<" "<<zxs.qry(las+1,now)<<endl;
            ans=(ans+1ll*zxs.qry(las+1,now)%mod*cnt%mod*(all-cnt)%mod)%mod;
            las=now;now=nxt[now];
        }
    }
    printf("%lld",ans);
    return 0;
}

T3 稳王

最优策略就是攒够了直接上

于是期望就是打不死的回合概率相加+1

于是dp+矩阵,求和公式直接上,dp容斥比较好

好像有好多重复计算...

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<<3)+(s<<1)+(ch^48);ch=getchar();}
    return s*t;
}
const int mod=998244353;
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[5][5];
    matrix(){memset(x,0,sizeof(x));}
    matrix operator * (matrix a)const{
        matrix ret;
        fo(i,0,4)fo(k,0,4)if(x[i][k])fo(j,0,4)ret.x[i][j]=(ret.x[i][j]+x[i][k]*a.x[k][j])%mod;
        return ret;
    }
    void clear(){memset(x,0,sizeof(x));}
};
matrix mksm(matrix x,int y){
    matrix ret;
    fo(i,0,4)ret.x[i][i]=1;
    while(y){
        if(y&1)ret=ret*x;
        x=x*x;y>>=1;
    }return ret;
}
int sol(int n){
    int ret=0,m=(n-1)>>1;
    ret=(ret+ksm(2,mod-2))%mod;
    ret=(ret+(1-ksm(ksm(3,mod-2),n)+mod)*ksm(2,mod-2))%mod;
// cerr<<ret<<endl;
    ret=(ret+(1-ksm(ksm(3,mod-2),m)+mod)*ksm(2,mod-2))%mod;
    ret=(ret+(ksm(3,m)-ksm(2,m+1)+1+mod)*ksm(ksm(3,m),mod-2))%mod;

    matrix ma,xs;ma.clear();xs.clear();
// cerr<<ret<<endl;
    ma.x[0][0]=1;
    xs.x[0][0]=xs.x[1][0]=ksm(3,mod-2);
    xs.x[0][1]=xs.x[1][2]=xs.x[2][2]=1;
    ma=ma*mksm(xs,n+2);
    ret=(ret+ma.x[0][2])%mod;
    ma.clear();xs.clear();
// cerr<<ret<<endl;
    ma.x[0][0]=1;
    xs.x[0][0]=ksm(3,mod-2);
    xs.x[0][1]=xs.x[1][2]=xs.x[2][2]=1;
    ma=ma*mksm(xs,n+2);
    ret=(ret-ma.x[0][2]+mod)%mod;
    ma.clear();xs.clear();
// cerr<<ret<<endl;
    ma.x[0][0]=1;
    xs.x[1][0]=ksm(3,mod-2);
    xs.x[0][1]=xs.x[1][2]=xs.x[2][2]=1;
    ma=ma*mksm(xs,n+2);
    ret=(ret-ma.x[0][2]+mod)%mod;
    ma.clear();xs.clear();
// cerr<<ret<<endl;
    ma.x[0][0]=1;
    xs.x[0][1]=xs.x[1][2]=xs.x[2][2]=1;
    ma=ma*mksm(xs,n+2);
    ret=(ret+ma.x[0][2])%mod;
    ma.clear();xs.clear();
// cerr<<ret<<endl;
    ma.x[0][0]=1;
    xs.x[0][0]=xs.x[2][0]=ksm(3,mod-2);
    xs.x[0][1]=xs.x[1][2]=xs.x[2][3]=xs.x[3][3]=1;
    ma=ma*mksm(xs,n+3);
    ret=(ret+ma.x[0][3])%mod;
    ma.clear();xs.clear();
// cerr<<ret<<endl;
    ma.x[0][0]=1;
    xs.x[0][0]=ksm(3,mod-2);
    xs.x[0][1]=xs.x[1][2]=xs.x[2][3]=xs.x[3][3]=1;
    ma=ma*mksm(xs,n+3);
    ret=(ret-ma.x[0][3]+mod)%mod;
    ma.clear();xs.clear();
// cerr<<ret<<endl;
    ma.x[0][0]=1;
    xs.x[2][0]=ksm(3,mod-2);
    xs.x[0][1]=xs.x[1][2]=xs.x[2][3]=xs.x[3][3]=1;
    ma=ma*mksm(xs,n+3);
    ret=(ret-ma.x[0][3]+mod)%mod;
    ma.clear();xs.clear();
// cerr<<ret<<endl;
    ma.x[0][0]=1;
    xs.x[0][1]=xs.x[1][2]=xs.x[2][3]=xs.x[3][3]=1;
    ma=ma*mksm(xs,n+3);
    ret=(ret+ma.x[0][3])%mod;
    ma.clear();xs.clear();
// cerr<<ret<<endl;
    ma.x[0][0]=1;
    xs.x[0][0]=xs.x[2][0]=xs.x[3][0]=ksm(3,mod-2);
    xs.x[0][1]=xs.x[1][2]=xs.x[2][3]=xs.x[3][4]=xs.x[4][4]=1;
    ma=ma*mksm(xs,n+4);
    ret=(ret+ma.x[0][4])%mod;
    ma.clear();xs.clear();
// cerr<<ret<<endl;
    ma.x[0][0]=1;
    xs.x[2][0]=xs.x[3][0]=ksm(3,mod-2);
    xs.x[0][1]=xs.x[1][2]=xs.x[2][3]=xs.x[3][4]=xs.x[4][4]=1;
    ma=ma*mksm(xs,n+4);
    ret=(ret-ma.x[0][4]+mod)%mod;
    ma.clear();xs.clear();
// cerr<<ret<<endl;
    ma.x[0][0]=1;
    xs.x[0][0]=xs.x[3][0]=ksm(3,mod-2);
    xs.x[0][1]=xs.x[1][2]=xs.x[2][3]=xs.x[3][4]=xs.x[4][4]=1;
    ma=ma*mksm(xs,n+4);
    ret=(ret-ma.x[0][4]+mod)%mod;
    ma.clear();xs.clear();
// cerr<<ret<<endl;
    ma.x[0][0]=1;
    xs.x[0][0]=xs.x[2][0]=ksm(3,mod-2);
    xs.x[0][1]=xs.x[1][2]=xs.x[2][3]=xs.x[3][4]=xs.x[4][4]=1;
    ma=ma*mksm(xs,n+4);
    ret=(ret-ma.x[0][4]+mod)%mod;
    ma.clear();xs.clear();
// cerr<<ret<<endl;
    ma.x[0][0]=1;
    xs.x[3][0]=ksm(3,mod-2);
    xs.x[0][1]=xs.x[1][2]=xs.x[2][3]=xs.x[3][4]=xs.x[4][4]=1;
    ma=ma*mksm(xs,n+4);
    ret=(ret+ma.x[0][4])%mod;
    ma.clear();xs.clear();
// cerr<<ret<<endl;
    ma.x[0][0]=1;
    xs.x[2][0]=ksm(3,mod-2);
    xs.x[0][1]=xs.x[1][2]=xs.x[2][3]=xs.x[3][4]=xs.x[4][4]=1;
    ma=ma*mksm(xs,n+4);
    ret=(ret+ma.x[0][4])%mod;
    ma.clear();xs.clear();
// cerr<<ret<<endl;
    ma.x[0][0]=1;
    xs.x[0][0]=ksm(3,mod-2);
    xs.x[0][1]=xs.x[1][2]=xs.x[2][3]=xs.x[3][4]=xs.x[4][4]=1;
    ma=ma*mksm(xs,n+4);
    ret=(ret+ma.x[0][4])%mod;
    ma.clear();xs.clear();
// cerr<<ret<<endl;
    ma.x[0][0]=1;
    xs.x[0][1]=xs.x[1][2]=xs.x[2][3]=xs.x[3][4]=xs.x[4][4]=1;
    ma=ma*mksm(xs,n+4);
    ret=(ret-ma.x[0][4]+mod)%mod;
    ma.clear();xs.clear();

    return (ret+1)%mod;
}
int T;
signed main(){
    freopen("stable.in","r",stdin);
    freopen("stable.out","w",stdout);
    T=read();
    while(T--)printf("%lld\n",sol(read()));
    return 0;
}
posted @ 2022-03-11 19:33  fengwu2005  阅读(62)  评论(0编辑  收藏  举报