hdu3652 && hdu 4722 && hdu3555

数位dp简单题

hdu3652

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
typedef long long ll;
const int N = 10+10;
int dig[N];
ll dp[N][N][2][20];
ll dfs(int len,int pre,int is,int sum,int f)
{
    if(len < 1) return is&&(sum==0) ;
    if(!f && dp[len][pre][is][sum]!=-1) return dp[len][pre][is][sum];
    int last = f ? dig[len] : 9;
    ll res = 0;
    for(int i=0;i<=last;i++)
    {
        res += dfs(len-1,i,is||(pre==1&&i==3),(sum*10+i)%13,f&&(i==last) );
    }
    if(!f) dp[len][pre][is][sum] = res;
    return res;
}
ll solve(int n)
{
    int len = 0;
    while(n)
    {
        dig[++len] = n % 10;
        n /= 10;
    }
    return dfs(len,0,0,0,1);
}
int main()
{
    int t,n;
    ll ans;
    memset(dp,-1,sizeof(dp));
    while(scanf("%d",&n)!=EOF)
    {
        ans = solve(n);
        printf("%lld\n",ans);
    }
    return 0;
}

hdu4722

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
const int N = 20+5;
int dig[N];
ll dp[N][20];
ll dfs(int len ,int sum,int f)
{
    if(len<1) return sum%10==0;
    if(!f && dp[len][sum]!=-1) return dp[len][sum];
    int last = f ? dig[len] : 9;
    ll res = 0;
    for(int i=0;i<=last;i++)
    {
        res += dfs(len-1,(sum+i)%10,f&&(i==last));
    }
    if(!f) dp[len][sum] = res;
    return res;
}
ll solve(ll n)
{
    if(n<0) return 0;
    int len = 0;
    while(n)
    {
        dig[++len] = n%10;
        n/=10;
    }
    return dfs(len,0,1);
}
int main()
{
    int t;
    int cas = 0;
    ll ans,l,r;
    cin>>t;
    memset(dp,-1,sizeof(dp));
    while(t--)
    {
        scanf("%lld%lld",&l,&r);
        ans = solve(r) - solve(l-1);
        printf("Case #%d: %lld\n",++cas,ans);
    }
    return 0;
}

hdu 3555

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
const int N = 20+5;
int dig[N];
ll dp[N][10][2];
ll dfs(int len ,int pre,int is,int f)
{
    if(len<1) return is;
    if(!f && dp[len][pre][is]!=-1) return dp[len][pre][is];
    int last = f ? dig[len] : 9;
    ll res = 0;
    for(int i=0;i<=last;i++)
    {
        res += dfs(len-1,i,is||(pre==4&&i==9),f&&(i==last));
    }
    if(!f) dp[len][pre][is] = res;
    return res;
}
ll solve(ll n)
{
    int len = 0;
    while(n)
    {
        dig[++len] = n%10;
        n/=10;
    }
    return dfs(len,0,0,1);
}
int main()
{
    int t;
    ll ans,r;
    cin>>t;
    memset(dp,-1,sizeof(dp));
    while(t--)
    {
        scanf("%lld",&r);
        ans = solve(r);
        printf("%lld\n",ans);
    }
    return 0;
}
时间: 2024-10-13 21:46:33

hdu3652 && hdu 4722 && hdu3555的相关文章

hdu 4722 Good Numbers(dp)

public static void main(String[] args) { String a=null; if("aa".equals(a))//这种情形,不出现空指针异常 //if(a.equals("aa"))//出现空指针异常 { System.out.println(true); } else { System.out.println(false); } } 上面的两句不同的比较语句测试,第一句不出现空指针异常,第二句出现. 所以在变量和常量比较的时候

hdu 4722 Good Numbers(初涉数位dp)

http://acm.hdu.edu.cn/showproblem.php?pid=4722 大致题意:若一个整数的各位数字之和是10的倍数,称这个数为"good number".给出区间[A,B],求出该区间内"good number"的数的个数. 第一道数位dp,折腾了半天才明白怎么回事. 设dp[site][mod]表示到第site位(由高位向低位)前面各位数字之和对10取余为mod的数的个数,进行记忆化搜索.有两个很重要的点,首先是变量up,表示是否到达边界

HDU 4722 Good Numbers (数位dp)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4722 思路:数位dp,dp[i][j]表示到第i位,数字和%10为j,然后进行dp,注意完全匹配的情况是要+1,而其他情况是从0 到 9 都要考虑 代码: #include <stdio.h> #include <string.h> #include <algorithm> #include <iostream> using namespace std; int

HDU 4722 Good Numbers 2013年四川省赛题

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4722 题目大意:给定一个区间,求区间中有多少个满足每位上的数的和是10的倍数. 解题思路:先打表暴力求出前200项符合条件的个数,然后再找规律. 0~9    0    1个 10~19  9   1个 20~-29  18  1个 0~100         10个 0~200         20个 基本规律:r/10-(l-1)/10;只需要找两端点是否在范围内即可 #include<cstd

hdu 4722 数位dp

/* 数位dp 用记忆化搜索写很清爽啊!不用推状态转移方程good. 开一个二维数组用来储存前len状态对10取余,有10种状态0-9; 然后直接过一遍就行了 */ #include<stdio.h> #include<string.h> #define ll __int64 #define N 20 ll digit[N],dp[N][11]; ll dfs(ll len,ll cnt,ll ok) { if(!len) { if(cnt==0)//如果可以整除返回1 retur

hdu 4722 Good Numbers(数位dp)

Good Numbers Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 3453    Accepted Submission(s): 1090 Problem Description If we sum up every digit of a number and the result can be exactly divided

【HDU 4722】Good Numbers

Good Numbers Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 3944 Accepted Submission(s): 1255 Problem Description If we sum up every digit of a number and the result can be exactly divided by 10,

HDU - 4722 Good Numbers 【找规律 or 数位dp模板】

If we sum up every digit of a number and the result can be exactly divided by 10, we say this number is a good number. You are required to count the number of good numbers in the range from A to B, inclusive. InputThe first line has a number T (T <=

dp题目列表

10271 - Chopsticks 10739 - String to Palindrome 10453 - Make Palindrome 10401 - Injured Queen Problem 825 - Walking on the Safe Side 10617 - Again Palindrome 10201 - Adventures in Moving - Part IV 11258 - String Partition 10564 - Paths through the Ho