• 数位DP初步 bzoj1026 hdu2089 hdu3555


    为了搞SCOI的几道题先做水数位。
    之前听过课,半懂不懂吧,现在清楚了些。

    这类题一般满足区间减法,即只需要我们求出(1,n)即可,然后打表也是为了sovle(DataType)服务。
    先想好怎么计算,再去想怎么打表。
    计算是一般存在这样的问题,就是比如n=abcdef,当a=6时,6开头的不能全算,那就只能先算1~5,然后理解为把6摆好,算下一位,这样我们发现,这个函数是没有包含n这个数的,所以调用是要调用sovle(n+1)

    不要62

    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
     
     
     
     1 #include<iostream>
     2 #include<algorithm>
     3 #include<cstdio>
     4 #include<cstdlib>
     5 #include<cstring>
     6 using namespace std;
     7 
     8 int dp[10][3];//dp[i]表示第i位,dp[i][0]吉利的,dp[i][1]第一位为2的吉利的,dp[i][2]为不吉利的 
     9 void table_maker() {
    10     dp[0][0]=1;
    11     for(int i=1;i<=6;i++){
    12         dp[i][0]=dp[i-1][0]*9-dp[i-1][1];
    13         dp[i][1]=dp[i-1][0];
    14         dp[i][2]=dp[i-1][2]*10+dp[i-1][1]+dp[i-1][0];
    15     }
    16 }
    17 int calc(int n) {
    18     int a[10]={0},ans=0,flag=0,tmp=n*10,len=0;
    19     for(;tmp/=10;)a[++len]=tmp%10;
    20     for(int i=len;i>=1;i--){
    21         ans+=a[i]*dp[i-1][2];
    22         if(flag)ans+=a[i]*dp[i-1][0];
    23         else{
    24             if(a[i]>4)ans+=dp[i-1][0];
    25             if(a[i]>6)ans+=dp[i-1][1];
    26             if(a[i+1]==6&&a[i]>2)ans+=dp[i][1];
    27             if(a[i]==4||(a[i+1]==6&&a[i]==2))flag=1;
    28         }
    29     }
    30     return n-ans;
    31 }
    32 
    33 int main() {
    34     freopen("in.txt","r",stdin);
    35 //    freopen("out.txt","w",stdout);
    36     
    37     table_maker();
    38     for(int l,r;~scanf("%d%d",&l,&r)&&(l||r);)printf("%d
    ",calc(r+1)-calc(l));
    39     return 0;
    40 }
     

    Bomb(要49)

    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 #include<iostream>
     2 #include<cstring>
     3 #include<cstdlib>
     4 #include<algorithm>
     5 #include<stdio.h>
     6 using namespace std;
     7 #ifndef UNIX
     8     #define LL "%I64d"
     9 #else
    10     #define LL "%lld"
    11 #endif
    12 const int N=20;
    13 typedef long long ll;
    14 ll dp[N][3],x;// dp[][0]不含49 dp[][1]不含49首位为9,dp[][2]含49
    15 void mk_tb() {
    16     dp[0][0]=1;
    17     for(int i=1; i<N; i++) {
    18         dp[i][0]=dp[i-1][0]*10-dp[i-1][1];
    19         dp[i][1]=dp[i-1][0];
    20         dp[i][2]=dp[i-1][2]*10+dp[i-1][1];
    21     }
    22 }
    23 ll f(ll n) {
    24     ll tmp=n,ans=0;
    25     int a[N]={0},flag=0;
    26     for(*a=0; tmp; tmp/=10)a[++*a]=tmp%10;
    27     for(int i=*a; i; i--) {
    28         ans+=a[i]*dp[i-1][2];
    29         if(flag)ans+=a[i]*dp[i-1][0];
    30         else {
    31             if(a[i]>4)ans+=dp[i-1][1];
    32             if(a[i+1]==4 && a[i]==9)flag=1;
    33         }
    34     }
    35     return ans;
    36 }
    37 int main() {
    38     freopen("in.txt","r",stdin);
    39     freopen("","w",stdout);
    40     mk_tb();int n;
    41     for(scanf("%d",&n);n--;){
    42         scanf(LL,&x);
    43         printf(LL"
    ",f(x+1));
    44     }
    45     
    46     return 0;
    47 }

    1026: [SCOI2009]windy数

    Time Limit: 1 Sec  Memory Limit: 162 MB
    Submit: 3075  Solved: 1376
    [Submit][Status]

    Description

    windy定义了一种windy数。不含前导零且相邻两个数字之差至少为2的正整数被称为windy数。 windy想知道,在A和B之间,包括A和B,总共有多少个windy数?

    Input

    包含两个整数,A B。

    Output

    一个整数。

    Sample Input

    【输入样例一】
    1 10
    【输入样例二】
    25 50

    Sample Output

    【输出样例一】
    9
    【输出样例二】
    20

    HINT

    【数据规模和约定】

    100%的数据,满足 1 <= A <= B <= 2000000000 。

     1 #include<iostream>
     2 #include<cstring>
     3 #include<cstdlib>
     4 #include<algorithm>
     5 #include<cstdio>
     6 #include<numeric>
     7 using namespace std;
     8 typedef int ll;
     9 const int N=10;
    10 ll dp[N+1][10];//dp[i][j]表示第i位为j的windy数的个数
    11 void mk_tb(){
    12     for(int i=0;i<=9;i++)dp[1][i]=1;
    13     for(int i=2;i<=N;i++){
    14         for(int j=0;j<=9;j++){
    15             for(int k=0;k<=9;k++){
    16                 if(abs(j-k)>=2){
    17                     dp[i][j]+=dp[i-1][k];
    18                 }
    19             }
    20         }
    21     }
    22 }
    23 ll f(ll n){
    24     int ans=0,a[N+1]={0},len=0;
    25     for(int tmp=n;tmp;tmp/=10)a[++len]=tmp%10;
    26     for(int i=1;i<len;i++)ans+=accumulate(dp[i]+1,dp[i]+N,0);
    27     for(int i=1;i<a[len];i++)ans+=dp[len][i];
    28     for(int i=len;--i;){
    29         for(int j=0;j<a[i];j++)if(abs(j-a[i+1])>=2)ans+=dp[i][j];
    30         if(abs(a[i]-a[i+1])<2)break;
    31     }
    32     return ans;
    33 }
    34 int main() {
    35     freopen("in.txt","r",stdin);
    36     freopen("","w",stdout);
    37     
    38     mk_tb();
    39     int a,b;
    40     scanf("%d%d",&a,&b);
    41     printf("%d
    ",f(b+1)-f(a));
    42     
    43     return 0;
    44 }
     
  • 相关阅读:
    关于SDK-manager中我们需要下载哪些?
    不只是撸代码搞鸡汤,也有故事!
    [Selenium]如何通过Selenium实现Ctrl+click,即按住Ctrl的同时进行单击操作
    【设计模式】单例模式
    【Java多线程】线程池学习
    【leetcode】147 Insertion Sort List
    【webssh】shellinabox搭建
    【SpringMVC】一次处理项目中文乱码的经历
    【Java多线程】JUC包下的工具类CountDownLatch、CyclicBarrier和Semaphore
    【leetcode】3 SUM
  • 原文地址:https://www.cnblogs.com/showson/p/4297141.html
Copyright © 2020-2023  润新知