noip模拟51[好IOI]

noip模拟51 solutions

好像是和别的学校一起考得

然后我交错比赛了,变成了\(IOI\)赛制,交上去就是俩\(AC\)

所以这次的题前两个过于水了。。。。

T1 茅山道术

就是找在当前条件下的,序列不重合划分的方案数,直接\(DP\),类似前缀和优化一下

AC_code
#include<bits/stdc++.h>
using namespace std;
#define re register int
const int N=1e6+5;
const int mod=1e9+7;
int n,c[N];
vector<int> vec[N];
int dp[N],sum[N],pos[N];
signed main(){
    freopen("magic.in","r",stdin);
    freopen("magic.out","w",stdout);
    scanf("%d",&n);
    for(re i=1;i<=n;i++)scanf("%d",&c[i]);
    n=unique(c+1,c+n+1)-c-1;
    for(re i=1;i<=n;i++)vec[c[i]].push_back(i),pos[i]=vec[c[i]].size()-1;
    dp[0]=0;
    for(re i=1;i<=n;i++){
        dp[i]=dp[i-1];
        if(pos[i])dp[i]=(dp[i]+sum[vec[c[i]][pos[i]-1]-1]+pos[i])%mod;
        if(pos[i])sum[i-1]=(dp[i-1]+sum[vec[c[i]][pos[i]-1]-1])%mod;
        else sum[i-1]=dp[i-1];
        //cout<<dp[i]<<" "<<sum[i-1]<<" "<<sum[vec[c[i]][pos[i]-1]-1]<<" "<<pos[i]<<endl;
    }
    //cout<<endl;
    printf("%d",dp[n]+1);
}

T2 泰拳警告

直接找规律,然后统计答案就好了

枚举平了多少局,后面第一个人必须胜一半以上

AC_code
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define re register int
const int N=3e6+5;
const int mod=998244353;
int n,p,pf[N],pg[N],jc[N],inv[N],ans,n2,m2[N];
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;
}
int C(int x,int y){
    return jc[x]*inv[y]%mod*inv[x-y]%mod;
}
signed main(){
    freopen("fight.in","r",stdin);
    freopen("fight.out","w",stdout);
    scanf("%lld%lld",&n,&p);
    pf[0]=pg[0]=1;n2=ksm(2,mod-2);
    pf[1]=ksm(p+2,mod-2);pg[1]=p*ksm(p+2,mod-2)%mod;
    jc[0]=jc[1]=1;m2[0]=1;m2[1]=2;
    for(re i=2;i<=n;i++){
        pf[i]=pf[i-1]*pf[1]%mod;
        pg[i]=pg[i-1]*pg[1]%mod;
        jc[i]=jc[i-1]*i%mod;
        m2[i]=m2[i-1]*2%mod;
    }
    inv[0]=1;inv[n]=ksm(jc[n],mod-2);
    for(re i=n-1;i>=1;i--)inv[i]=inv[i+1]*(i+1)%mod;
    //cout<<ksm(9,mod-2)<<" "<<ksm(3,mod-2)<<endl;
    for(re i=0;i<=n;i++){
        int tmp;
        if((n-i)&1)tmp=m2[n-i]*n2%mod*C(n,i)%mod;
        else tmp=(m2[n-i]*n2%mod+mod-C(n-i,n-i>>1)*n2%mod)%mod*C(n,i)%mod;
        ans=(ans+pg[i]*pf[n-i]%mod*(i+1)%mod*tmp%mod)%mod;
        //cout<<pf[i]<<" "<<pg[n-i]<<" "<<ans<<endl;
    }
    printf("%lld",ans);
}

T3 万猪拱塔

首先看题要看准,\(k\)是互不相同的

所以我当前矩形的数一定是一个连续的区间

直接枚举这个区间判断是否构成矩形

按着题解上说的,枚举右端点,更新所在的四个小矩形,线段树

AC_code
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define re register int 
const int N=2e5+5;
const int mod=998244353;
int n,m,ans,rp;
vector<int> jz[N],id[N];
struct position{
    int i,j;
    position(){}
    position(int x,int y){i=x;j=y;}
}ti[N];
struct XDS{
    #define ls x<<1
    #define rs x<<1|1
    int sum[N*4],csm[N*4],res[N*4],tag[N*4];
    int re_csm,re_res;
    void pushup(int x){
        sum[x]=min(sum[ls],sum[rs]);csm[x]=0;res[x]=0;
        if(sum[x]==sum[ls])csm[x]+=csm[ls],res[x]+=res[ls];
        if(sum[x]==sum[rs])csm[x]+=csm[rs],res[x]+=res[rs];
    }
    void pushdown(int x){
        if(!tag[x])return ;
        tag[ls]+=tag[x];
        tag[rs]+=tag[x];
        sum[ls]+=tag[x];sum[rs]+=tag[x];
        tag[x]=0;
    }
    void build(int x,int l,int r){
        if(l==r){
            csm[x]=1;sum[x]=0;res[x]=l;
            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>qr)return ;
        if(ql<=l&&r<=qr){
            sum[x]+=v;tag[x]+=v;
            return ;
        }
        pushdown(x);
        int mid=l+r>>1;
        if(ql<=mid)ins(ls,l,mid,ql,qr,v);
        if(qr>mid)ins(rs,mid+1,r,ql,qr,v);
        pushup(x);return ;
    }
    void query(int x,int l,int r,int ql,int qr){
        if(ql<=l&&r<=qr){
            if(sum[x]==4)re_csm+=csm[x],re_res+=res[x];
            return ;
        }
        pushdown(x);
        int mid=l+r>>1;
        if(ql<=mid)query(ls,l,mid,ql,qr);
        if(qr>mid)query(rs,mid+1,r,ql,qr);
        pushup(x);
    }
    #undef ls
    #undef rs
}xds;
int ji[5],cnt;
signed main(){
    freopen("pig.in","r",stdin);
    freopen("pig.out","w",stdout);
    scanf("%lld%lld",&n,&m);
    jz[0].resize(m+5);jz[n+1].resize(m+5);
    for(re i=1;i<=n;i++){
        jz[i].resize(m+5);
        id[i].resize(m+5);
        for(re j=1;j<=m;j++){
            scanf("%lld",&jz[i][j]);
            ti[jz[i][j]]=position(i,j);
        }
    }
    //cout<<"Sb"<<endl;
    xds.build(1,1,n*m);
    for(re i=1;i<=n*m;i++){
        int x=ti[i].i,y=ti[i].j;
        cnt=0;
        if(jz[x-1][y-1]<i)ji[++cnt]=jz[x-1][y-1];
        if(jz[x][y-1]<i)ji[++cnt]=jz[x][y-1];
        if(jz[x-1][y]<i)ji[++cnt]=jz[x-1][y];
        sort(ji+1,ji+cnt+1);
        xds.ins(1,1,n*m,ji[cnt]+1,i,1);
        for(re j=cnt,bas=-1;j>=1;j--)xds.ins(1,1,n*m,ji[j-1]+1,ji[j],bas),bas=-bas;
        cnt=0;
        if(jz[x-1][y+1]<i)ji[++cnt]=jz[x-1][y+1];
        if(jz[x][y+1]<i)ji[++cnt]=jz[x][y+1];
        if(jz[x-1][y]<i)ji[++cnt]=jz[x-1][y];
        sort(ji+1,ji+cnt+1);
        xds.ins(1,1,n*m,ji[cnt]+1,i,1);
        for(re j=cnt,bas=-1;j>=1;j--)xds.ins(1,1,n*m,ji[j-1]+1,ji[j],bas),bas=-bas;
        cnt=0;
        if(jz[x+1][y-1]<i)ji[++cnt]=jz[x+1][y-1];
        if(jz[x][y-1]<i)ji[++cnt]=jz[x][y-1];
        if(jz[x+1][y]<i)ji[++cnt]=jz[x+1][y];
        sort(ji+1,ji+cnt+1);
        xds.ins(1,1,n*m,ji[cnt]+1,i,1);
        for(re j=cnt,bas=-1;j>=1;j--)xds.ins(1,1,n*m,ji[j-1]+1,ji[j],bas),bas=-bas;
        cnt=0;
        if(jz[x+1][y+1]<i)ji[++cnt]=jz[x+1][y+1];
        if(jz[x][y+1]<i)ji[++cnt]=jz[x][y+1];
        if(jz[x+1][y]<i)ji[++cnt]=jz[x+1][y];
        sort(ji+1,ji+cnt+1);
        xds.ins(1,1,n*m,ji[cnt]+1,i,1);
        for(re j=cnt,bas=-1;j>=1;j--)xds.ins(1,1,n*m,ji[j-1]+1,ji[j],bas),bas=-bas;
        xds.re_csm=xds.re_res=0;
        xds.query(1,1,n*m,1,i);
        //cout<<xds.re_res<<" "<<xds.re_csm<<endl;
        (ans+=1ll*i*xds.re_csm-xds.re_res+xds.re_csm)%=mod;
    }
    printf("%lld",ans);
}

T4 沽

上一篇:一种删除指定文件夹和保留指定文件夹的操作


下一篇:P1038 神经网络(60)