转自: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);
}
}