zoukankan      html  css  js  c++  java
  • [CSP-S模拟测试76]题解

    咕咕咕

    A.序列

    无解情况:$n>a*b$或$n<a+b-1$

    把序列分成B段,每段内部上升,各段分界处构成下降子序列。

    实现并不是太简单,要动态地考虑一下边界什么的。

    #include<cstdio>
    #include<iostream>
    #include<cstring>
    using namespace std;
    int T,n,a,b;
    void work()
    {
        scanf("%d%d%d",&n,&a,&b);
        if(n>1LL*a*b||n<a+b-1)
        {
            puts("No");
            return ;
        }
        puts("Yes");
        int beg=n-a+1;
        for(int i=beg;i<=n;i++)
            printf("%d ",i);
        if(b==1)return ;
        b--;
        int bl=(beg-1)/b,now=beg-bl;
        while(b)
        {
            bl=(beg-1)/b;
            now=beg-bl;
            for(int i=now;i<beg;i++)
                printf("%d ",i);
            beg=now;
            b--;
        }
        putchar('
    ');
    }
    
    int main()
    {
        scanf("%d",&T);
        while(T--)work();
        return 0;
    }
    

    B.购物

    按套路来讲,答案区间应该是连续的?

    并不是。如果把$a[]$排序后求前缀和,会发现如果$frac{a_i}{2} > sum_{i-1}$,那么$(sum_{i-1},frac{a_i}{2}]$就是一段缺口。因为已经排过序了,所以这段缺口是无法用其它方式补上的。

    #include<cstdio>
    #include<iostream>
    #include<algorithm>
    using namespace std;
    typedef long long ll;
    const int N=1e5+5;
    int read()
    {
        int x=0,f=1;char ch=getchar();
        while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
        while(isdigit(ch))x=x*10+ch-'0',ch=getchar();
        return x*f;
    }
    int n;
    ll a[N],sum[N],ans;
    ll div2(ll x)
    {
        return (x-1>>1)+1;
    }
    
    int main()
    {
        n=read();
        for(int i=1;i<=n;i++)
            a[i]=read();
        sort(a+1,a+n+1);
        for(int i=1;i<=n;i++)
        {
            if(div2(a[i])>sum[i-1])ans+=div2(a[i])-sum[i-1]-1;
            sum[i]=sum[i-1]+a[i];
        }
        cout<<sum[n]-ans<<endl;
        return 0;
    }
    

    C.计数

    没有限制的话就是Catalan数。

    设$dp[l][r]$为在前序遍历上的区间为$[l,r]$,以$l$为根的子树中的方案数。

    用二维前缀和记录限制,枚举左右子树分配的大小转移即可。

    #include<cstdio>
    #include<iostream>
    #include<cstring>
    using namespace std;
    int read()
    {
        int x=0,f=1;char ch=getchar();
        while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
        while(isdigit(ch))x=x*10+ch-'0',ch=getchar();
        return x*f;
    }
    typedef long long ll;
    const ll mod=1e9+7;
    const int N=405;
    int T,n,m,g[N][N],sum[N][N];
    ll dp[N][N];
    int get(int x,int y,int xx,int yy)
    {
        return sum[xx][yy]-sum[x-1][yy]-sum[xx][y-1]+sum[x-1][y-1];
    }
    void work()
    {
        n=read();m=read();
        memset(g,0,sizeof(g));
        memset(sum,0,sizeof(sum));
        memset(dp,0,sizeof(dp));
        for(int i=1;i<=m;i++)
        {
            int x=read(),y=read();
            g[x][y]++;
        }
        for(int i=1;i<=n;i++)
        {
            dp[i][i]=1;
            for(int j=1;j<=n;j++)
                sum[i][j]=sum[i-1][j]+sum[i][j-1]-sum[i-1][j-1]+g[i][j];
        }
        for(int len=2;len<=n;len++)
        {
            for(int i=1;i+len-1<=n;i++)
            {
                int j=i+len-1;
                if(!get(i,i+1,i,j))(dp[i][j]+=dp[i+1][j])%=mod;
                if(!get(i+1,i,j,i))(dp[i][j]+=dp[i+1][j])%=mod;
                for(int k=i+1;k<=j-1;k++)
                    if(!get(i,i+1,i,k)&&!get(k+1,i,j,k))
                        (dp[i][j]+=dp[i+1][k]*dp[k+1][j])%=mod;
            }
        }
        printf("%lld
    ",dp[1][n]);
        return ;
    }
    
    int main()
    {
        T=read();
        while(T--)work();
        return 0;
    }
    
  • 相关阅读:
    slice和splice的区别
    Js中获取对象的所有key值
    设置layUI的时间laydate 结束时间大于开始时间
    vscode前端常用插件推荐,搭建JQuery、Vue等开发环境
    安装vue脚手架
    es6中...是什么意思
    html转义字符换行以及回车等的使用
    10款让人惊叹的HTML5/jQuery图片动画特效
    基于GIS技术的水利一张图平台
    BIM + 3D GIS在岩溶强发育区跨海盾构隧道施工中的实践应用
  • 原文地址:https://www.cnblogs.com/Rorschach-XR/p/11741700.html
Copyright © 2011-2022 走看看