省选模拟24

刚考完学考下午就考试了,好像这个题都挺简单??

最终我只有70分,还挺不甘心的,最后仍然是发现自己的思路方向本身就有问题,还是能力的欠缺!

可能经过这么长时间的训练,最后提升的是代码能力,思维能力还是很差......

T1 排队

虽然很快就找到了dp方程,但是无法用矩阵优化,甚至写出了拉格朗日插值发现不是一个多项式...

根据模数很小这个东西,我们可以造出1000个矩阵,然后转移

也可以对答案找循环节!!

当然还有一个可以直接用矩阵优化的方程!!

设dp[i][j][k]表示当前放了前i大的数,有j段,有k个不好的点

我们从大到小依次加入,一个点可以单独形成一个段,也可以接在某一个段的两侧,也可以用来合并两个段

最后要的是dp[n][1][m],这样保证了你钦定为不好的点一定是不好的点,因为合并只能用更小的合并,于是这个东西两侧一定比他小

转移很简单,可以用矩阵乘优化

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=1e6+5;
const int M=105;
int n,m,p;
struct matrix{
    int x[M][M];
    matrix(){memset(x,0,sizeof(x));}
    matrix operator * (matrix a)const{
        matrix ret;
        fo(i,1,m*m)fo(k,1,m*m)if(x[i][k])fo(j,1,m*m)ret.x[i][j]=(ret.x[i][j]+x[i][k]*a.x[k][j])%p;
        return ret;
    }
}ma,xs;
int id(int x,int y){return (x-1)*m+y;}
signed main(){
    freopen("queue.in","r",stdin);
    freopen("queue.out","w",stdout);
    n=read();m=read();p=read();
    fo(i,1,m)fo(j,1,m){
        if(i!=m&&j!=m)xs.x[id(i,j)][id(i+1,j+1)]=i+1;
        if(i>1)xs.x[id(i,j)][id(i-1,j)]=i-1;
        xs.x[id(i,j)][id(i,j)]=i<<1;
    }
    ma.x[1][id(1,1)]=1;n--;
    while(n){
        if(n&1)ma=ma*xs;
        xs=xs*xs;n>>=1;
    }
    printf("%lld",ma.x[1][id(1,m)]);
    return 0;
}

T2 昵称

考场上费劲心思想预处理一些东西,最后一个一个直接填,于是写的非常麻烦!!

其实到这里的时候就可以停下来了,科学追求的是简洁而又正确,如果过于麻烦,就可以放弃这个思路了

于是我们可以通过简单的数位dp得到当前的方案数!!

我们记忆化一下这样复杂度就对了

AC_code
#include<bits/stdc++.h>
using namespace std;
#define int __int128
#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=1055;
char a[N];int n,len,m,s[N];
int ksm(int x,int y){
    int ret=1;
    while(y){
        if(y&1)ret=ret*x;
        x=x*x;y>>=1;
    }return ret;
}
int dp[N][N],f[N];
bool jud(int ln,int &lim){
    int tmp=lim;lim-=ksm(10,ln);
    if(lim<=0){lim=tmp;return true;}
    fo(i,2,ln+1){
        lim-=f[i-1]*ksm(10,ln-i+1);
        if(lim<=0){lim=tmp;return true;}
    }return false;
}
int nxt[N],fail[N][15];
int g[N][N][2];
int dfs(int x,int y,int t){
    if(x==m){
        if(t)return 0;
        else return 1;
    }
    if(~g[x][y][t])return g[x][y][t];
    int ret=0;fo(i,0,9)ret+=dfs(x+1,fail[y][i],t&(fail[y][i]!=len));
    //cerr<<(ll)x<<" "<<(ll)y<<" "<<(ll)t<<endl;
    return g[x][y][t]=ret;
}
signed main(){
    freopen("nickname.in","r",stdin);
    freopen("nickname.out","w",stdout);
    scanf("%s",a+1);len=strlen(a+1);n=read();
    fo(i,1,len)s[i]=a[i]-'0';
    for(int i=2,j=0;i<=len;i++){
        while(j&&s[i]!=s[j+1])j=nxt[j];
        if(s[i]==s[j+1])j++;nxt[i]=j;
    }
    fo(i,0,len){
        fo(j,0,9)fail[i][j]=fail[nxt[i]][j];
        if(i!=len)fail[i][s[i+1]]=i+1;
    }
    fo(i,1,9){
        if(i==s[1])dp[1][1]++;
        else dp[1][0]++;
    }
    fo(i,1,18)fo(j,0,len-1){
        if(!dp[i][j])continue;
        fo(k,0,9)dp[i+1][fail[j][k]]+=dp[i][j];
    }
    fo(i,1,18){
        fo(j,0,len-1)f[i]+=dp[i][j];
        int now=nxt[len];
        while(now)f[i]-=dp[i][len-now],now=nxt[now];
    }
    m=0;while(!jud(m,n))m++;m+=len;
    memset(g,-1,sizeof(g));
    int now=0,fl=1;
    fo(i,1,m){
        fo(j,0,9){
            if(i==1&&j==0)continue;
            int res=dfs(i,fail[now][j],fl&(fail[now][j]!=len));
            //cerr<<(ll)i<<" "<<(ll)fail[now][j]<<" "<<(ll)res<<endl;
            if(n<=res){
                now=fail[now][j];
                if(now==len)fl=0;
                printf("%lld",(ll)j);
                break;
            }n-=res;
        }
        // cerr<<(ll)i<<endl;
    }
    return 0;
}

T3 帝国防卫

考场上甚至没有来得及看这个题

发现最多更改\(log^2\)层,于是我们用深度颗线段树来解决这个东西

每一个点只会变得小于零一次,一旦发现小于零了,那就直接搜下去

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 inf=0x3f3f3f3f3f3f3f3f;
int n,m;
struct BIT{
    int tr[N];
    void ins(int x){
        //cout<<"ins"<<" "<<x<<endl;
        for(int i=x;i<=n;i+=(i&-i))tr[i]++;
    }
    int query(int x){
        int ret=0;
        for(int i=x;i;i-=(i&-i))ret+=tr[i];
        return ret;
    }
    int qry(int l,int r){
        return query(r)-query(l-1);
    }
}bit;
struct XDS{
    int rt[N];
    struct POT{
        int ls,rs;
        int mn,tg;
    }tr[N*35];
    int seg;
    XDS(){tr[0].mn=inf;}
    int newpot(){return ++seg;}
    void pushup(int x){
        tr[x].mn=min(tr[tr[x].ls].mn,tr[tr[x].rs].mn);
        return ;
    }
    void pushdown(int x){
        if(tr[x].ls){
            tr[tr[x].ls].mn+=tr[x].tg;
            tr[tr[x].ls].tg+=tr[x].tg;
        }
        if(tr[x].rs){
            tr[tr[x].rs].mn+=tr[x].tg;
            tr[tr[x].rs].tg+=tr[x].tg;
        }
        tr[x].tg=0;
    }
    void chg(int x,int l,int r){
        if(l==r)return tr[x].mn=inf,bit.ins(l),void();
        int mid=l+r>>1;if(tr[x].tg)pushdown(x);
        if(tr[tr[x].ls].mn<=0)chg(tr[x].ls,l,mid);
        if(tr[tr[x].rs].mn<=0)chg(tr[x].rs,mid+1,r);
        pushup(x);return ;        
    }
    void ins(int &x,int l,int r,int ql,int qr,int v){
        if(ql>qr)return ;
        if(!x)x=newpot();
        if(ql<=l&&r<=qr){
            tr[x].mn+=v;tr[x].tg+=v;
            if(tr[x].mn<=0)chg(x,l,r);
            return ;
        }
        int mid=l+r>>1;if(tr[x].tg)pushdown(x);
        if(ql<=mid&&(tr[x].ls||v>0))ins(tr[x].ls,l,mid,ql,qr,v);
        if(qr>mid&&(tr[x].rs||v>0))ins(tr[x].rs,mid+1,r,ql,qr,v);
        pushup(x);return ;
    }
}xds;
int c[N];
struct E{int to,nxt;}e[N*2];
int head[N],rp;
void add_edg(int x,int y){
    e[++rp].to=y;e[rp].nxt=head[x];head[x]=rp;
}
int dfn[N],dfm[N],cnt,dep[N],fa[N];
void dfs(int x,int f,int d){
    dfn[x]=++cnt;dep[x]=d;fa[x]=f;
    xds.ins(xds.rt[d],1,n,dfn[x],dfn[x],c[x]);
    for(int i=head[x];i;i=e[i].nxt){
        int y=e[i].to;
        if(y==f)continue;
        dfs(y,x,d+1);
    }dfm[x]=cnt;
}
signed main(){
    freopen("empire.in","r",stdin);
    freopen("empire.out","w",stdout);
    n=read();
    fo(i,1,n)c[i]=read();
    fo(i,1,n-1){
        int x=read(),y=read();
        add_edg(x,y);add_edg(y,x);
    }
    dfs(1,0,1);
    m=read();
    while(m--){
        int tp,x,a,now;
        tp=read();
        if(tp==1){
            x=read();a=read();
            for(int i=dep[x],na=a;na;i++,na>>=1)xds.ins(xds.rt[i],1,n,dfn[x],dfm[x],-na);
            now=fa[x];a>>=1;
            while(now&&a){
                for(int i=dep[now],na=a;na;i++,na>>=1){
                    xds.ins(xds.rt[i],1,n,dfn[now],dfn[x]-1,-na);
                    xds.ins(xds.rt[i],1,n,dfm[x]+1,dfm[now],-na);
                }x=now;now=fa[now];a>>=1;
            }
        }
        if(tp==2){
            x=read();
            printf("%lld\n",bit.qry(dfn[x],dfm[x]));
        }
    }
    return 0;
}
posted @ 2022-03-04 15:10  fengwu2005  阅读(42)  评论(0)    收藏  举报