Tsinsen A1516. fx 数位dp

题目: http://www.tsinsen.com/A1516

A1516. fx

时间限制:2.0s   内存限制:256.0MB

总提交次数:164   AC次数:72   平均分:51.28

将本题分享到:

查看未格式化的试题   提交   试题讨论

试题来源

  中国国家队清华集训 2013-2014 第四天

问题描述

  对于一个n位的十进制数x(AnAn-1……A1),我们定义它的权重为:
  F(x)=An*2n-1+An-1*2n-2+……+A1*20
  现在,给你两个十进制数A和B,请计算出在闭区间[0, B]之中,有多少个数x的权重不大于A的权重,即F(x)<=F(A)。由于答案可能很大,你只需要输出答案对1000000007(109 + 7)取模的结果即可。

输入格式

  第一行一个正整数T,表示测例的个数。
  随后T行,每行描述一个测例,包含两个非负整数A、B,之间用空格隔开。含义见问题描述。

输出格式

  对于每个测例,单独输出一行”Case #t: ans”,其中t表示测例编号,从1开始递增,ans表示该组测例的答案(对1000000007取模后的结果)。

样例输入

3
0 100
1 10
5 100

样例输出

Case #1: 1
Case #2: 2
Case #3: 13

样例说明

  对于Case #3,符合条件的数有0, 1, 2, 3, 4, 5, 10, 11, 12, 13, 20, 21, 100,共13个。

  //样例描述有修改,请注意!

数据规模及约定

  对于20%的数据,A, B <= 109
  对于30%的数据,A, B <= 1018

  对于100%的数据,A,B <= 10200,T<=5。

题解:

数位dp

f[i][j]为到第i位,差值之和为j的方案数.

但16和17行没有理解太懂,关于 差值+30 不太清楚。QAQ

如果哪位高人看懂了,可以留言。万分感谢。??Orz

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define MOD 1000000007
 4 int f[210][66],A[210],B[210];
 5 char s1[210],s2[210];
 6 int read()
 7 {
 8     int s=0,fh=1;char ch=getchar();
 9     while(ch<‘0‘||ch>‘9‘){if(ch==‘-‘)fh=-1;ch=getchar();}
10     while(ch>=‘0‘&&ch<=‘9‘){s=s*10+(ch-‘0‘);ch=getchar();}
11     return s*fh;
12 }
13 int Dfs(int len,int tot,int flag)//当前到达第len位,差值之和为tot,flag为是否限制(0代表不限制,1代表限制)
14 {
15     if(len==0)return tot>=0;
16     if(tot<-30)return 0;//这两句!!!
17     if(tot>30)tot=30;//这两句!!!
18     if(flag==0&&f[len][tot+30]!=-1)return f[len][tot+30];
19     int end=flag?B[len]:9,i,ret=0;
20     for(i=0;i<=end;i++)ret=(ret+Dfs(len-1,(tot+A[len]-i)*2,flag&&(i==end)))%MOD;
21     if(flag==0)f[len][tot+30]=ret;
22     return ret;
23 }
24 int main()
25 {
26     int case1=0,T,la,lb,i;
27     T=read();
28     while(T--)
29     {
30         scanf("\n%s %s",s1+1,s2+1);
31         la=strlen(s1+1);
32         lb=strlen(s2+1);
33         memset(A,0,sizeof(A));
34         memset(B,0,sizeof(B));
35         memset(f,-1,sizeof(f));
36         for(i=1;i<=la;i++)A[i]=s1[la-i+1]-‘0‘;//要从高位枚举,所以要把序列倒过来.
37         for(i=1;i<=lb;i++)B[i]=s2[lb-i+1]-‘0‘;//同上.
38         if(la>lb)swap(la,lb);//取出长度大的.
39         printf("Case #%d: %d\n",++case1,Dfs(lb,0,1));
40     }
41     fclose(stdin);
42     fclose(stdout);
43     return 0;
44 }
时间: 2024-10-18 20:12:36

Tsinsen A1516. fx 数位dp的相关文章

bzoj 1026 [SCOI2009]windy数——数位dp水题

题目:https://www.lydsy.com/JudgeOnline/problem.php?id=1026 迷恋上用dfs写数位dp了. #include<iostream> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int N=15; int l,r,dg[N],dp[N][N]; int dfs(int p,int lst,bo

51Nod 1009 数字1的个数 | 数位DP

题意: 小于等于n的所有数中1的出现次数 分析: 数位DP 预处理dp[i][j]存 从1~以j开头的i位数中有几个1,那么转移方程为: if(j == 1) dp[i][j] = dp[i-1][9]*2+pow(10,i-1);else dp[i][j] = dp[i-1][9]+dp[i][j-1]; 然后注意下对于每个询问统计的时候如果当前位为1需要额外加上他后面所有位数的个数,就是n%pow(10,i-1); 这样总复杂度log(n)*10 #include <bits/stdc++.

HDU 3555 Bomb (数位DP)

数位dp,主要用来解决统计满足某类特殊关系或有某些特点的区间内的数的个数,它是按位来进行计数统计的,可以保存子状态,速度较快.数位dp做多了后,套路基本上都差不多,关键把要保存的状态给抽象出来,保存下来. 简介: 顾名思义,所谓的数位DP就是按照数字的个,十,百,千--位数进行的DP.数位DP的题目有着非常明显的性质: 询问[l,r]的区间内,有多少的数字满足某个性质 做法根据前缀和的思想,求出[0,l-1]和[0,r]中满足性质的数的个数,然后相减即可. 算法核心: 关于数位DP,貌似写法还是

51nod1043(数位dp)

题目链接:https://www.51nod.com/onlineJudge/questionCode.html#!problemId=1043 题意:中文题诶- 思路:数位dp 我们用dp[i][j]来存储长度为2*i且一半和为j的所有情况(包括前导0的情况),为了方便我们现在只讨论其一半的和的情况,因为如果包括前导0的话其两边的情况是一样的: 我们假设再长度为i-1的数字最前面加1位数字k,0<=k<=9(这位数字加在哪里并不影响答案,因为我们在计算i-1长度的时候已经计算了所有组合情况,

数位dp

1.[hdu3709]Balanced Number 1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<string> 5 #include<cstdlib> 6 #include<algorithm> 7 #include<ctime> 8 #include<cmath> 9 #include<queue>

【HDU 3652】 B-number (数位DP)

B-number Problem Description A wqb-number, or B-number for short, is a non-negative integer whose decimal form contains the sub- string "13" and can be divided by 13. For example, 130 and 2613 are wqb-numbers, but 143 and 2639 are not. Your task

hdu 5898 odd-even number 数位DP

odd-even number Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 716    Accepted Submission(s): 385 Problem Description For a number,if the length of continuous odd digits is even and the length

LightOJ1068 Investigation(数位DP)

这题要求区间有多少个模K且各位数之和模K都等于0的数字. 注意到[1,231]这些数最大的各位数之和不会超过90左右,而如果K大于90那么模K的结果肯定不是0,因此K大于90就没有解. 考虑到数据规模,数据组数,这题状态这么表示: dp[i][j][k]:位数为i模K结果为j且各位数之和模K结果为k的数字个数 然后就是转移方程,最后就是统计.. 统计部分好棘手...半乱搞下AC的..还是对数位DP的这一部分太不熟悉了. 1 #include<cstdio> 2 #include<cstr

HDU 4734 F(x)(数位DP)

Description For a decimal number x with n digits (A nA n-1A n-2 ... A 2A 1), we define its weight as F(x) = A n * 2 n-1 + A n-1 * 2 n-2 + ... + A 2 * 2 + A1 * 1. Now you are given two numbers A and B, please calculate how many numbers are there betwe