1. 程式人生 > 其它 >省選模擬22

省選模擬22

剛考完學考下午就考試了,好像這個題都挺簡單??

最終我只有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;
}
QQ:2953174821