zoukankan      html  css  js  c++  java
  • [ARC 066] Tutorial

    Link:

    ARC 066 传送门

    C:

    如果存在可行方案则答案为$2^{n/2}$

    #include <bits/stdc++.h>
    
    using namespace std;
    #define X first
    #define Y second
    typedef long long ll;
    typedef pair<int,int> P;
    const int MAXN=1e5+10,MOD=1e9+7;
    int n,x,res[MAXN];
    
    int main()
    {
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&x);
            int rk=(n-1+x)/2;
            if(!res[rk+1]) res[rk+1]=i;
            else if(!res[n-rk]) res[n-rk]=i;
            else return puts("0"),0;
        }
        int res=1;
        for(int i=1;i<=n/2;i++) (res*=2)%=MOD;
        printf("%d",res);
        return 0;
    }
    Problem C

    D:

    挺不错的一道数位$dp$

    由于无法直接计算$sum$和$xor$的对数,因此考虑枚举$a,b$,而将$sum,xorle n$作为限制条件

    又因为公式:$a+b=aXORb+2*(a&b)$,所以$a+ble aXORb$,只考虑$a+b$的限制即可

    此时问题转化为对于每个$sumle n$求$xor$的取值个数

    这样就可以用$dp[i][s]$表示前$i$位确定,$a+b$的和为$s$的个数,每次分$a,b$在该位上总共有几个1转移

    (按每位1的个数转移才不会考虑异或与和同时相同的情况!)

    但这样复杂度是不对的,在枚举$s$上明显花费了不必要的时间

    根据一般数位$dp$记录上限的思想,如果前$i$位的$n-sge 2$,这些数以后都保证合法,就能统一计算了

    这样就从$dp[i][s]$变成了$dp[i][0/1/2]$

    #include <bits/stdc++.h>
    
    using namespace std;
    #define X first
    #define Y second
    typedef long long ll;
    typedef pair<int,int> P;
    #define MAX_D 64
    #define MOD ((ll)1e9 + 7)
    ll N,dp[MAX_D][3],res;int nxt;
    
    int main() 
    {    
        scanf("%lld",&N);
        dp[MAX_D-1][0]=1;
        for(int i=MAX_D-1;i>0;i--) 
            for(int j=0; j <= 2; j++)
                for(int k=0;k<=2;k++) 
                {
                    nxt=j*2+((N>>(i-1))&1)-k;
                    if (nxt<0) continue;
                    nxt=nxt>2?2:nxt;
                    (dp[i-1][nxt]+=dp[i][j])%=MOD;
                }
        res=0;
        for (int i=0;i<=2;i++) (res+=dp[0][i])%=MOD;
        printf("%lld
    ", res);
        return 0;
    }
    Solution A

    从后往前用记忆化搜索的形式写起来更加方便

    一开始将上限值就设为$n$,每次确定最后一位取几个以后去掉最后一位,不用考虑和的合法性了

    #include <bits/stdc++.h>
    
    using namespace std;
    #define X first
    #define Y second
    typedef long long ll;
    typedef pair<int,int> P;
    const int MOD=1e9+7;
    map<ll,ll> dp;ll n;
    
    ll dfs(ll x)
    {
        if(dp.count(x)) return dp[x];
        return dp[x]=(dfs(x>>1)+dfs((x-1)>>1)+dfs((x-2)>>1))%MOD;
    }
    
    int main()
    {
        scanf("%lld",&n);
        dp[0]=1;dp[1]=2;
        printf("%lld",dfs(n));
        return 0;
    }
    Solution B

    E:

    首先要观察出几点性质:

    1、只有在减号后可能加括号

    2、括号不可能嵌套超过两层,否则可以转化为只有两层的简化情况

    这样就可以记录$dp[0/1/2]$分别表示当前还有几个左括号未匹配的最大值来$dp$了

    #include <bits/stdc++.h>
    
    using namespace std;
    typedef long long ll;
    int n,x;char op;ll dp[3],nxt[3];
    
    int main()
    {
        scanf("%d%d",&n,&dp[0]);
        dp[1]=dp[2]=-1ll<<60;
        for(int i=1;i<n;i++)
        {
            scanf(" %c%d",&op,&x);
            if(op=='-') x=-x;
            nxt[0]=dp[0]+x,nxt[1]=dp[1]-x,nxt[2]=dp[2]+x;
            dp[0]=max(nxt[0],max(nxt[1],nxt[2]));
            if(op=='+') dp[1]=max(nxt[1],nxt[2]),dp[2]=nxt[2];
            else dp[1]=dp[0],dp[2]=max(nxt[1],nxt[2]);
        }
        printf("%lld",dp[0]);
        return 0;
    }
    Solution A

    其实也可以不用$dp$,考虑如果在某个减号后加了第一个括号的最优解

    发现此时能保证将下一个减号后的值都变为正贡献,但对当前位到下一个减号间的值是无能为力的

    这样枚举第一个括号的位置对答案更新即可

    #include <bits/stdc++.h>
    
    using namespace std;
    #define X first
    #define Y second
    typedef long long ll;
    typedef pair<int,int> P;
    const int MAXN=1e5+10;
    char op[MAXN];
    int n,dat[MAXN],nxt[MAXN],fst;
    ll suf[MAXN],cur,res=-1ll<<60;
    
    int main()
    {
        scanf("%d%d",&n,&fst);
        for(int i=1;i<n;i++)
            scanf(" %c%d",&op[i],&dat[i]);
        cur=n;
        for(int i=n-1;i;i--)
        {
            suf[i]=suf[i+1]+dat[i];
            if(op[i]=='-') nxt[i]=cur,cur=i;
        }
        cur=0;
        for(int i=1;i<n;i++)
            if(op[i]=='-') 
                res=max(res,cur-suf[i]+2*suf[nxt[i]]),cur-=dat[i];
            else cur+=dat[i];
        res=max(res,cur);
        printf("%lld",res+fst);
        return 0;
    }
    Solution B

    F:

  • 相关阅读:
    PS 色调——颜色运算
    [ExtJS5学习笔记]第二十二节 Extjs5中使用beforeLabelTpl配置给标签增加必填选项星号标志
    [ExtJS5学习笔记]第二十一节 Extjs5中使用config配置给ext.widget或者create方法传递参数
    PS 滤镜——素描算法(一)
    [ExtJS5学习笔记]第二十节 Extjs5配合数组的push方法,动态创建并加载组件
    [ExtJS5学习笔记]第十九节 Extjs5中通过设置form.Panel的FieldSet集合属性控制多个field集合
    【翻译】Ext JS最新技巧——2014-9-10
    Ext JS 5的声明式事件监听
    BZOJ_3477_[Usaco2014 Mar]Sabotage_二分答案
    BZOJ_3012_[Usaco2012 Dec]First!_trie树+拓扑排序
  • 原文地址:https://www.cnblogs.com/newera/p/9548047.html
Copyright © 2011-2022 走看看