数位DP:Bomb、不要62

Bomb

http://acm.hdu.edu.cn/showproblem.php?pid=3555
Problem Description
The counter-terrorists found a time bomb in the dust. But this time the terrorists improve on the time bomb. The number sequence of the time bomb counts from 1 to N. If the current number sequence includes the sub-sequence “49”, the power of the blast would add one point.
Now the counter-terrorist knows the number N. They want to know the final points of the power. Can you help them?

Input
The first line of input consists of an integer T (1 <= T <= 10000), indicating the number of test cases. For each test case, there will be an integer N (1 <= N <= 2^63-1) as the description.
The input terminates by end of file marker.
Output
For each test case, output an integer indicating the final points of the power.
Sample Input

3
1
50
500

Sample Output

0
1
15

Hint
From 1 to 500, the numbers that include the sub-sequence “49” are “49”,“149”,“249”,“349”,“449”,“490”,“491”,“492”,“493”,“494”,“495”,“496”,“497”,“498”,“499”,
so the answer is 15.
问题描述:
输入一个数,输出1 到这个数之间有多少个数带49.
CODE:

#include <iostream>
using namespace std;
typedef long long LL;
int dig[20];
LL dp[20][2];
LL dfs(int len,bool if4,bool limit)
{
    if(len==0)
        return 1ll;  //long long 型的1
    if(!limit && dp[len][if4])
        return dp[len][if4];
    LL cnt=0;
    LL n=limit?dig[len]:9;
    for(int i=0; i<=n; i++)
    {
        if(if4&&i==9)  //如果上一位是4,当轮到9的时候就不计数了。
            continue;
        cnt+=dfs(len-1,i==4,limit&&i==n);
    }
    if(!limit)
        dp[len][if4]=cnt;
    return cnt;
}
LL cal(LL n)
{
    int k=0;
    while(n!=0)
    {
        dig[++k]=n%10;
        n/=10;
    }
    return dfs(k,false,true);
}
int main()
{
    int t;
    cin>>t;
    while(t--)
    {
        LL n;
        cin>>n;
        cout<<n+1-cal(n)<<endl;
    }
    return 0;
}

不要62

http://acm.hdu.edu.cn/showproblem.php?pid=2089
Problem Description
杭州人称那些傻乎乎粘嗒嗒的人为62(音:laoer)。
杭州交通管理局经常会扩充一些的士车牌照,新近出来一个好消息,以后上牌照,不再含有不吉利的数字了,这样一来,就可以消除个别的士司机和乘客的心理障碍,更安全地服务大众。
不吉利的数字为所有含有4或62的号码。例如:
62315 73418 88914
都属于不吉利号码。但是,61152虽然含有6和2,但不是62连号,所以不属于不吉利数字之列。
你的任务是,对于每次给出的一个牌照区间号,推断出交管局今次又要实际上给多少辆新的士车上牌照了。
Input
输入的都是整数对n、m(0<n≤m<1000000),如果遇到都是0的整数对,则输入结束。
Output
对于每个整数对,输出一个不含有不吉利数字的统计个数,该数值占一行位置。
Sample Input

1 100
0 0

Sample Output

80

CODE:

#include <iostream>

using namespace std;
typedef long long LL;
int dig[20];
LL dp[20][2];
LL dfs(int len,bool if6,bool limit)
{
    if(len==0)
        return 1ll;
    if(!limit && dp[len][if6])
        return dp[len][if6];
    LL cnt=0;
    LL n=limit?dig[len]:9;
    for(int i=0; i<=n; i++)
    {
        if(i==4)
            continue; //遇到4就不计数
        if(if6&&i==2)  //上一位是6,轮到2就不计数
            continue;
        cnt+=dfs(len-1,i==6,limit&&i==n);
    }
    if(!limit)
        dp[len][if6]=cnt;
    return cnt;
}
LL cal(LL n)
{
    int k=0;
    while(n!=0)
    {
        dig[++k]=n%10;
        n/=10;
    }
    return dfs(k,false,true);
}
int main()
{
    LL N,M;
    while(cin>>N>>M&&(N||M))
    {
        cout<<cal(M)-cal(N-1)<<endl;
    }
    return 0;
}


视频讲解

关于不要62的:

常规做法会超时:
CODE:

#include <iostream>
#include <string>
#include <sstream>

using namespace std;

int main()
{
    int n,m;
    while(cin>>n>>m)
    {
        if(n==0&&m==0)
            break;
        int i,re;
        re=0;
        string str1="4";
        string str2="62";
        for(i=n; i<=m; i++)
        {
            stringstream ss;
            ss<<i;
            string str=ss.str();
            if(str.find(str1)==string::npos&&str.find(str2)==string::npos)
                re++;
        }
        cout<<re<<endl;
    }
    return 0;
}


知识补充:

一、将int类型转为字符串

1、
使用标准C语言将int类型转为字符串方法为:

int a = 10;
char *intStr = itoa(a);
printf("%s\n",intStr);

char* 转为string 直接用 string s= string(intStr) ; 就可以转换。
2、
使用C++语言将int类型转为字符串方法为:

(注:使用stringstream要包含#include <sstream>头文件)
int a = 10;
stringstream ss;
ss << a;
string str = ss.str();

3、
但以上两种方法都不是最简单的方法。
使用std::to_string方法才是最简单的方法。
不但可以转换10进制整形数据,还可以是16进制的。

#include <string>
#include <iostream>
int value=10;
std::string s = std::to_string(value) ;
std::cout<<s<<std::endl;
std::cout<<std::to_string(0xfa11);

二、字符串中查找另一个字符串

1、
C++的string类提供了字符串中查找另一个字符串的函数find。

其重载形式为:

string::size_type string::find(string &);

功能为在string对象中,查找参数string类型的字符串是否存在,如果存在,返回起始位置。不存在则返回 string::npos。

#include <iostream>
#include <string>
using namespace std;
int main()
{
    string a="abcdefghigklmn";
    string b="def";
    string c="123";
    string::size_type idx;

    idx=a.find(b);//在a中查找b.
    if(idx == string::npos )//不存在。
        cout << "not found\n";
    else//存在。
        cout <<"found\n";
    idx=a.find(c);//在a中查找c。
    if(idx == string::npos )//不存在。
        cout << "not found\n";
    else//存在。
        cout <<"found\n";
    return 0;
}

2、
在C语言中,字符串存储为字符数组,以’\0’结束。 在C的接口中,有strstr函数,可以在字符串中查找另一个字符串。

char * strstr(const char *str1, const char *str2);

功能为在str1中查找str2,如果存在,那么返回查找到的起始指针,否则返回NULL。

#include <iostream>
#include <string>
#include <cstring>
using namespace std;
int main()
{
    string a="abcdefghigklmn";
    char *b="def";
    char *c="123";

    if(strstr(a.c_str(), b) == NULL)//在a中查找b,如果不存在,
        cout << "not found\n";//输出结果。
    else//否则存在。
        cout <<"found\n"; //输出结果。
    if(strstr(a.c_str(), c) == NULL)//在a中查找b,如果不存在,
        cout << "not found\n";//输出结果。
    else//否则存在。
        cout <<"found\n"; //输出结果。
    return 0;
}

非动态规划做法(已通过):
CODE:

#include <iostream>
#include <cstring>
#include <string>
#include <stdlib.h>
#include <stdio.h>
#include <sstream>
using namespace std;
int a[1000002];
void code()
{
    int i;
    char str1[]="4",str2[]="62",str[10];
    a[0]=0;
    for(i=1; i<=1000000; i++)
    {
        itoa(i,str,10);
        if(strstr(str,str1)==NULL&&strstr(str,str2)==NULL)
        {
            a[i]=1;
        }
        else
        {
            a[i]=0;
        }
    }
}
int main()
{
    code();
    int n,m;
    while(cin>>n>>m)
    {
        if(n==0&&m==0)
            break;
        int sum=0;
        for(int i=n;i<=m;i++)
        {
            sum+=a[i];
        }
        cout<<sum<<endl;
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_44350170/article/details/102924868
今日推荐