17浙江省赛 数位dp or xjb乱搞


转自:http://www.cnblogs.com/wuwangchuxin0924/p/6749799.html


居然可以用数位dp

,看来自己还是没有学好啊。。。但是用苏大佬的做法做的还是wa了,,不知道还有哪里没有考虑周全,,不过那种思想还是挺好的。。

//

大概对于数位dp 的进一步思考:

就是有挺多是重复计算的,如果位数相同的话,这个时候只要是sum相同的,那么之后的结果也会是相同的,就不用重复计算了。。、

像这个地方就存在很多重复计算、、


#include<iostream>
#include<string>
#include<cstring>
#include<algorithm>
#include<cstdio>

using namespace std;
#define bug1 cout<<"bug1"<<endl;
#define bug2 cout<<"bug2"<<endl;
#define bug3 cout<<"bug3"<<endl;
#define mem(a,b) memset(a,b,sizeof(a));
#define sf scanf
#define pf printf
#define LL long long

int dig[20];
int t;
LL l,r,n;
int num[16]={6,2,5,5,4,5,6,3,
             7,6,6,5,4,5,5,4};
char a[20];
LL dp[20][1005];
LL dfs(int pos ,LL sum, bool limit){
    if(pos<0)return sum;
    if(!limit&&dp[pos][sum]!=-1)return dp[pos][sum];
    int up=limit?dig[pos]:15;
    LL tmp=0;
    for(int i=0;i<=up;++i){
        tmp+=dfs(pos-1,sum+num[i],limit&&i==dig[pos]);
    }
    if(!limit)dp[pos][sum]=tmp;
    return tmp;
}
LL judge(LL n){
    for(int i=0;i<8;++i){
        dig[i]=n%16;
        n/=16;
    }
    return dfs(7,0,1);
}
int main(){
    int t;
    sf("%d",&t);
    mem(dp,-1);
    while(t--){
        sf("%lld %llx",&r,&n);
        r--;
        l=n;
        r+=l;
        if(r>(LL)4294967295){
            r%=(LL)(4294967296);
            printf("%lld\n",judge((LL)4294967295)-judge(l-1)+judge(r));
        }else{
            printf("%lld\n",judge(r)-judge(l-1));
        }
    }
}
another做法 wa了。。

#include<iostream>
#include<string>
#include<cstring>
#include<algorithm>
#include<cstdio>

using namespace std;
#define bug1 cout<<"bug1"<<endl;
#define bug2 cout<<"bug2"<<endl;
#define bug3 cout<<"bug3"<<endl;
#define mem(a,b) memset(a,b,sizeof(a));
#define sf scanf
#define pf printf
#define LL long long
int a[20];
int cnt[20]={6,2,5,5,4,5,6,3,7,6,6,5,4,5,5,4};
long long  p[20];
char tmp[20];

long long getsumR(int *t,int x){
    long long ret=0;
    for(int i=x;i<=8;++i){
        ret+=t[i]*p[i];
    }
    return ret;
}

long long sumL(int*t,int x){
    long long ret=0;
    for(int i=1;i<=x;++i){
        ret+=cnt[t[i]];
    }
    return ret;
}

long long sumR(int *t,int x){
    long long ret=0;
    for(int i=x;i<=8;++i){
        for(int j=0;j<16;++j){
            ret+=p[i]*cnt[j];
        }
    }
    return ret;
}

int main(){
    int t;
    sf("%d",&t);
    p[8]=1;
    for(int i=7;i>=1;--i){
        p[i]=p[i+1]*16;
    }
    //cout<<p[1]<<' '<<p[2]<<endl;
    while(t--){
        int n;
        sf("%d",&n);
        int time=n;
        sf("%s",tmp+1);
        for(int i=1;i<=8;++i){
            if(tmp[i]>='0'&&tmp[i]<='9'){
                a[i]=tmp[i]-'0';
            }
            else if(tmp[i]>='A'){
                a[i]=tmp[i]-'A'+10;
            }
        }
        long long ans=0;
        for(int i=1;i<=8;++i){
            while(time>=p[i]){
                time-=p[i];

                long long getr=getsumR(a,i+1);
                ans+=sumL(a,i)*(p[i]-getr);//进制前
                a[i]++;
                ans+=sumL(a,i)*getr;//进制后。
                ans+=sumR(a,i+1);//
                int t=i;//模拟进位
                while(a[t]>=16){
                    a[t-1]++;
                    a[t]-=16;
                    t--;
                }/*
                for(int k=1;k<=8;++k){
                    pf("%d",a[k]);
                }puts("");*/

            }
        }
        pf("%lld\n",ans);
    }
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值