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

省選模擬27

聯賽後第一次rk1吧!?還挺激動的

開場發現checker是exe,人傻了,於是我就想要換windows,然而沒換成因為windows沒有g++

於是萬能的水哥出場了,把exe轉成了linux下的可執行檔案!!!

第一題開場想到了根號的構造方法,最後搞到了正解

第二題看了一會就走了,這玩意實在是不可做

第三題沒多久就想到了是狀壓dp,可以叫插頭dp?寫的時候細節多得很,一一直寫到了11點30,那時的我認為11點50結束考試,給我緊張壞了,11點44的時候4*4的樣例都過不了,於是我放棄了,花了2分鐘打了個暴力就交上去了

交完之後發現woc12點10分結束!!然後繼續調,揪出來兩個小錯誤,然後就切掉了

T1 分裂

一開始想的是我每一層只拿一個下去,最後二進位制拆分一下,這樣是根號的

然後想一層只剩下一個,剩下的都拿下去,然後發現這樣不可行

於是想到了一個折半的做法,每層拿下一半去!!哈哈哈,我可真是個天才

發現最後一層剩下的那一半可以下放兩層,這樣一定可以滿足條件,最後二進位制拆分微調就好了

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=1e7+5;
int T,n,buc[30],gx[30],all[30],ans[30];
signed main(){
    freopen("split.in","r",stdin);
    freopen("split.out","w",stdout);
    int now=1;
    gx[1]=1;all[1]=1;
    fo(i,2,25){
        all[i]=all[i-1]-(now+1>>1);
        buc[i-1]=(now>>1);
        now=((now+1)>>1)*i;
        gx[i]=now;
        all[i]+=gx[i];
    }
    T=read();
    while(T--){
        n=read();
        if(n==1){printf("1\n1 1\n");continue;}
        if(n==3||n==5||n==8){printf("-1\n");continue;}
        memset(ans,0,sizeof(ans));
        fo(nn,1,25)if(n<all[nn]){nn-=1;
            int ys=n-all[nn];
            fo(i,1,nn-1)ans[i]=buc[i];
            ans[nn]=gx[nn];ans[0]=nn;
            if(ys>ans[nn-1]*(nn-1)){
                ans[0]=nn+1;ys-=ans[nn-1]*(nn-1);
                ans[nn]+=ans[nn-1]*nn;ans[nn-1]=0;
                if(ys>=nn){
                    ans[nn+1]+=ys/nn*(nn+1);ans[nn]-=ys/nn;
                    ys%=nn;
                }
            }
            else if(ys>=nn-1){
                ans[nn]+=ys/(nn-1)*nn;ans[nn-1]-=ys/(nn-1);
                ys%=(nn-1);
            }
            fu(i,ans[0],1)if(ys>=i&&ans[i]){
                ans[i]--;ans[i+1]+=i+1;
                ys-=i;ans[0]=max(ans[0],i+1);
            }
            if(ys){
                fo(i,2,ans[0]-1)if(ans[i+1]>i+1){
                    ans[i]++;ans[i+1]-=i+1;
                    ans[i+1]--;ans[i+2]+=i+2;
                    ans[0]=max(ans[0],i+2);
                    break;
                }
            }
            int res=0;
            fo(i,1,ans[0])if(ans[i])res++;
            printf("%lld\n",res);
            fo(i,1,ans[0])if(ans[i])printf("%lld %lld\n",i,ans[i]);
            break;
        }
    }
    return 0;
}

T2 未來

遇到這種題,先想想怎麼能把這玩意轉化成運算,因為只有算數題才能加速,並且找到可以簡化的地方

於是我們給每個字元對映到0,1,2上,發現變換就是\(a_i=(a_i+a_{i+1})*2\%3\)

於是這個東西我們依舊不知道怎麼做,但是發現好像一層一層的展開最後是個楊輝三角

想到組合數,發現是對3取模,lucas定理,我們每次轉移三進位制的某一位,就是\(3^k \choose i\),這樣i只有兩位是有值的0和\(3^k\)

於是有了logm的做法

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=5e5+5;
char ch[N];
int n,m,a[N],b[N];
signed main(){
    freopen("future.in","r",stdin);
    freopen("future.out","w",stdout);
    n=read();m=read();
    scanf("%s",ch);
    fo(i,0,n-1){
        if(ch[i]=='r')a[i]=0;
        else if(ch[i]=='g')a[i]=1;
        else a[i]=2;
    }
    while(m){
        int stp=1;
        while(stp<=m/3)stp*=3;
        while(m>=stp){
            fo(i,0,n-1)b[i]=(a[i]+a[(i+stp)%n])*2%3;
            fo(i,0,n-1)a[i]=b[i];m-=stp;
        }
    }
    fo(i,0,n-1)printf("%c",a[i]?(a[i]==2?'b':'g'):'r');
}

T3 回憶

直接狀壓dp,由於寬度最大是6,最多的聯通塊個數是3,可以4進位制壓位,壓成12位

用map記錄每一個聯通塊的大小,以及歷史最大值,轉移就行了

細節賊多!!!

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=41;
const int mod=998244353;
int ksm(int x,int y){
    int ret=1;
    while(y){
        if(y&1)ret=1ll*ret*x%mod;
        x=1ll*x*x%mod;y>>=1;
    }return ret;
}
int n,m,jz[N][N],ans;
struct node{
    int a[5];
    node(){memset(a,0,sizeof(a));}node(int x,int y,int z,int w=0){a[1]=x;a[2]=y;a[3]=z;a[4]=max(w,max(a[1],max(a[2],a[3])));}
    bool operator < (node x)const{
        if(a[1]!=x.a[1])return a[1]<x.a[1];
        if(a[2]!=x.a[2])return a[2]<x.a[2];
        if(a[3]!=x.a[3])return a[3]<x.a[3];
        return a[4]<x.a[4];
    }
};
map<node,int> dp[N][1<<12];
int fai[15],bai[15],zti[15],bti[15];
int find(int x){return fai[x]==x?x:fai[x]=find(fai[x]);}
int get(int s,int i){return (s>>(i-1)*2)&3;}
int bia[15];
signed main(){
    freopen("memory.in","r",stdin);
    freopen("memory.out","w",stdout);
    n=read();m=read();
    if(n>m)fo(i,1,n)fo(j,1,m)jz[i][j]=read();
    else {
        fo(i,1,n)fo(j,1,m)jz[j][i]=read();
        swap(n,m);
    }
    dp[0][0][node(0,0,0,0)]=1;
    int u=(1<<m*2)-1;
    fo(x,1,n){
        fo(s,0,u){
            if(dp[x-1][s].size()==0)continue;
            fo(i,1,m)fai[i]=bai[i]=i,zti[i]=1<<get(s,i);
            fo(i,m+1,2*m)fai[i]=bai[i]=i,zti[i]=0;
            fo(i,1,m)fo(j,i+1,m){
                if(get(s,i)==get(s,j)){
                    int fx=find(i),fy=find(j);
                    if(fx==fy)continue;
                    fai[fy]=fx;zti[fy]|=zti[fx];
                }
            }
            fo(i,1,2*m)bai[i]=fai[i],bti[i]=zti[i];
            for(pair<node,int> o:dp[x-1][s]){
                if(!o.second)continue;
                fo(t,0,(1<<m)-1){
                    fo(i,1,2*m)fai[i]=bai[i],zti[i]=bti[i],bia[i]=0;
                    int las=0,num=0,ss=0;node res=node(0,0,0,o.first.a[4]);
                    fo(i,1,m+1)if(!((t>>i-1)&1)){
                        if(las+1>i-1){las=i;continue;}
                        fo(j,las+1,i-1){
                            if(!get(s,j))continue;
                            int fx=find(j+m),fy=find(j);
                            if(fx==fy)continue;
                            fai[fx]=fy;zti[fy]|=zti[fx];
                        }
                        fo(j,las+1,i-2){
                            int fx=find(j+m),fy=find(j+m+1);
                            if(fx==fy)continue;
                            fai[fx]=fy;zti[fy]|=zti[fx];
                        }las=i;
                    }
                    fo(i,1,m){
                        if(!((t>>i-1)&1))continue;
                        if(!bia[find(i+m)]){
                            bia[find(i+m)]=++num;
                            fo(j,1,3)if((zti[find(i+m)]>>j)&1){
                                res.a[bia[find(i+m)]]+=o.first.a[j];
                            }
                        }
                        ss|=(1<<(i-1)*2)*bia[find(i+m)];
                        res.a[bia[find(i+m)]]++;
                    }
                    res.a[4]=max(res.a[4],max(res.a[1],max(res.a[2],res.a[3])));
                    int gl=1;
                    fo(i,1,m){
                        if((t>>i-1)&1)gl=1ll*gl*jz[x][i]%mod;
                        else gl=1ll*gl*(mod+1-jz[x][i])%mod;
                    }
                    if(!gl)continue;
                    dp[x][ss][node(res)]=(dp[x][ss][node(res)]+1ll*o.second*gl%mod)%mod;
                }
            }
        }
    }
    fo(s,0,u){
        for(pair<node,int> o:dp[n][s]){
            int mx=o.first.a[4];
            ans=(ans+1ll*mx*o.second%mod)%mod;
        }
    }
    printf("%lld",ans);
    return 0;
}
QQ:2953174821