多校(第四场)C题 数位DP

题目大意是给出一个式子an 求其前n项的和。

首先我们可以发现 在n mod4 为0、3时 an=a[n/2]+1,n mod4为1、2时an=a[n/2]-1。
而从a1到an要经过log2 an次这样的加减,可以转化成二进制位上的问题。
把n化为二进制数组b,当某位bi与bi-1组成的二进制为0、3时+1,为1、2时-1,例如bi==1,bi-1==0,二进制就是10,十进制为2,此时-1。
此时我们就可以在log复杂度内求出an。

然后我们再利用数位dp,来求出前n项的和。

dp存储的第一维len表示位数。
第二维 if pre==2表示bi前一项为空,故不计算bi+1与bi,else pre表示前一位的值。
第三维为sum,表示前面位数累计的和,因为会有负值,故加上64最后再减去并取绝对值。

另外,因为对于+1时的0、3二进制分别为00,11,故我们可以通过bi+1==bi来判断加减。
以下为数位dp的代码。
#include <bits/stdc++.h>
using namespace std;
const long long mod=1000000007;
long long i,n,m,dp[64][3][128],a[64],T;
long long dfs(int len,bool maxi,int pre,int sum)
{
    if(dp[len][pre][sum]!=-1&&maxi==0)return dp[len][pre][sum];
    long long cnt=0;
    if(!len)return abs(sum-64);
    int maxn=maxi?a[len]:1;
    for(int i=0;i<=maxn;i++)
    {
        if(pre==2)
        {
            if(i)cnt+=dfs(len-1,maxi&&i==a[len],i,sum);
            else cnt+=dfs(len-1,maxi&&i==a[len],pre,sum);
        }
        else
        {
            if(i==pre)cnt+=dfs(len-1,maxi&&i==a[len],i,sum+1);
            else cnt+=dfs(len-1,maxi&&i==a[len],i,sum-1);
        }
    }
    cnt%=mod;
    return maxi?cnt:dp[len][pre][sum]=cnt;
}
long long div(long long tmp)
{
    int p=0;
    while(tmp)a[++p]=tmp%2,tmp/=2;
    return dfs(p,1,2,64);
}
int main()
{
    memset(dp,-1,sizeof(dp));
    scanf("%lld",&T);
    while(T--)
    {
        scanf("%lld",&n);
        printf("%lld\n",div(n));
    }
    return 0;
}



全部评论
请问为什么要开一维记录前面sum的值呢,后面的状态不是不会受到前面sum的影响吗?
点赞 回复
分享
发布于 2018-08-01 14:49

相关推荐

好吧&nbsp;这次不能偷懒了,周记必须开始了1.首先肯定是javase,最近的话是把集合,线程学了,然后坦克也完善到了0.5版本了,就差后面反射学完再完善后面的版本当然了后面其实还有IO流,通信然后学到数据库过后我的项目才是真正启动,因为时间已经不够了,按照我自己的进度到后面老师要求的假答辩我只能提交个前端项目了,到后面完善了技术栈过后再独立完成前端+后端的开发&nbsp;现在刚陷入线程,反射,其实我知道这些东西目前对我来说都用不上,但是后面涉及到的多线程,高并发又会用到这些基础,然后面试官又喜欢拷打这些,就让我放不下,一直跟着走。现在我也觉得反正打基础嘛,还有时间,慢慢加油吧。add:其实我自己也在想,为什么不跟着学校走,直接前端到后端短时间直通,现在基本上想通了,就是因为我从大一开始的不作为,没有规划学习路线,没有规划自己的工作方向等等。放弃了超级多的学习机会,现在每天这么累就当在赎罪了。2.然后就是英语六级,这个东西说实话有点不自量力了,其实我自己的英语一直不是很好,在这里面我也觉得花费了很多时间,但是我也没去反馈验证,正确来说过了四级我就应该把重点放到提升技术栈上面来了,因为我没有考研科研打算,我只想早点搞钱。3.其实就在前几天,已经启动了算法刷题模式,因为之前有点数据结构基础,不用去很系统地学习,但是暴力解法以后面试或者写代码感觉都要吃亏,算法基础我觉得还是要有的,而且面试也有要求。add:然后我就发现了个宝藏网站“代码随想录”,这个网站已经根据算法的刷题路线题目已经规划好了,从数组开始刷就真的很奈斯。其实这个星期的心里路程特别精彩,一直处于情绪波动的状态,但目前结果对我来说还不错。也差不多了,说下这个星期生活的事情现在自己篮球中投命中率已经非常高了,对喜欢听刷网声音的我来说非常舒服和开心哈哈哈再说个倒霉事吧,星期四晚上的时候想出去唱歌,话筒音响都背好了,屁股没坐热就开始下雨了,真的是fuck,好气好气&nbsp;!杰伦的中国风歌曲我都提前彩排了&nbsp;!最后呢,今晚上和室友出去吃饭了,这种机会已经太少了,我明白我之前学习上的不作为导致我现在很少有出去玩和手机游戏娱乐的机会,今晚上顶着晚归的风险也要citywalk。over #如果可以选,你最想从事什么工作# #能让你振作起来的一句话# #我的求职思考#
点赞 评论 收藏
转发
点赞 收藏 评论
分享
牛客网
牛客企业服务