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;
}
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;
}
相关文章推荐
- HDU 4722 Good Numbers(数位DP)
- hdu 4722 Good Numbers 数位dp
- hdu 4722 Good Numbers 数位DP
- hdu4722之简单数位dp
- hdu 4722 Good Numbers(规律题)
- HDU--4722
- HDU 4722 Good Numbers(DP)
- [数位dp] hdu 4722 Good Numbers
- HDU 4722 Good Numbers
- hdu 4722 Good Numbers 2013 ACM/ICPC Asia Regional Online —— Warmup2
- hdu 4722
- HDU 4722 Good Numbers(找规律)
- hdu 4722 Good Numbers
- hdu4722
- hdu 4722 Good Numbers
- hdu 4722 Good numbers(数位DP)
- HDU 4722 Good Numbers
- HDU 4722 数位DP
- HDU-4722-线段树优化dp
- HDU 4722 Good Numbers