您的位置:首页 > 其它

hdu 4722

2013-09-12 00:32 323 查看
昨天才学得数位dp,今天刚好网路热身赛遇见一个,而且还比较简单,不过傻X的把dp定义成int没找出错,跪了一小时才发现,不过不得不感叹数位dp真的太适合做类题了,很契合计算机的思想,虽然这种题找规律也可以做,不过既然是编程还是契合计算机思想比较好。

1.数位dp方法:
#include<stdio.h>
#include<string.h>
#include<stdlib.h>

const int max=20;
int dp[max][10];
int digit[max];

long long dfs(int pos,int mod,int flag){
if(pos==-1)return mod==0;
if(flag&&dp[pos][mod]!=-1)return dp[pos][mod];
long long sum=0;
int size = flag?9:digit[pos];
for(int i=0;i<=size;i++){
int MOD=(mod+i)%10;
sum+=dfs(pos-1,MOD,flag||i<size);
}
if(flag)dp[pos][mod]=sum;
return sum;
}

long long cal(long long n){
if(n<0)return 0;
int len = 0;
while(n){
digit[len++] = n%10;//转化成对应的数位
n/=10;
}
return dfs(len-1,0,0);//记忆化搜索
}

int main(){
#ifdef T
freopen("input.txt","r",stdin);
freopen("output.txt","w",stdout);
#endif
long long r,l;
int t;
memset(dp,-1,sizeof(dp));//这里初始化一次就好,每次算的信息还可以供以后用
scanf("%d",&t);
for(int i=1;i<=t;i++){
scanf("%I64d %I64d",&l,&r);
printf("Case #%d: %I64d\n",i,cal(r)-cal(l-1));
}
return 0;
}


2.找规律,例如911,那么肯地有91个数十的取法,最后还得看末尾的个位数与前面的每个digit相加取10的模是否为0,为0还要+1变为92,不过这里好像没有存在+尾数刚好可以得到0的情况所以输出就是91.找规律一定要把所有情况都想到,且处理要普遍化不能太多特例,这样很容易出现某些考虑不到的地方半天找不出错。
#include<cstdio>
#include<cstdlib>

long long cal(long long num){
long long temp=num;
long long ans=num/10;
int sum=0;
int pre=temp%10;
temp/=10;
while(temp){
sum+=temp%10;
temp/=10;
}
for(int i=0;i<=pre;i++)if((sum+i)%10==0)
{ ans++; break; }
return ans;
}

int main(){
#ifdef T
freopen("input.txt","r",stdin);
freopen("output.txt","w",stdout);
#endif
long long r,l;
int t;
scanf("%d",&t);
for(int i=1;i<=t;i++){
scanf("%I64d %I64d",&l,&r);
printf("Case #%d: %I64d\n",i,cal(r)-cal(l-1));
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  数位dp or 找规律