数位dp(求1-n中数字1出现的个数)

题意:求1-n的n个数字中1出现的个数。

解法:数位dp,dp[pre][now][equa] 记录着第pre位为now,equa表示前边是否有降数字(即后边可不可以随意取,true为没降,true为已降);常规的记忆化搜索

代码:

/******************************************************
* author:xiefubao
*******************************************************/
#pragma comment(linker, "/STACK:102400000,102400000")
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <queue>
#include <vector>
#include <algorithm>
#include <cmath>
#include <map>
#include <set>
#include <stack>
#include <string.h>
//freopen ("in.txt" , "r" , stdin);
using namespace std;

#define eps 1e-8
const double pi=acos(-1.0);
typedef long long LL;
const int Max=10100;
const int INF=1000000007;
int fac[10];
void init()
{
    fac[0]=1;
    fac[1]=1;
    for(int i=2; i<10; i++)
        fac[i]=fac[i-1]*10;
}
char s[20];
int dp[20][20][2];
int n;
int num[20];
int dfs(int pre,int now,int equa)
{
    if(pre==0)
        return now==1;
    if(dp[pre][now][equa]!=-1)
        return dp[pre][now][equa];
    int ans=0;
    if(now==1&&!equa)
        ans+=fac[pre+1];
    if(now==1&&equa)
        ans+=n%fac[pre+1]+1;
    int en=equa?num[pre-1]:9;
    for(int i=0;i<=en;i++)
    ans+=dfs(pre-1,i,equa&&i==num[pre-1]);
    return dp[pre][now][equa]=ans;
}
int getans(int t)
{
    int p=0;
    memset(dp,-1,sizeof dp);
    while(t)
    {
        num[p++]=t%10;
        t/=10;
    }
    int ans=0;
    for(int i=0; i<=num[p-1]; i++)
    {
        ans+=dfs(p-1,i,i==num[p-1]);
    }
    return ans;
}
int main()
{
    init();
    while(cin>>n)
    {
        printf("%d\n",getans(n));
    }
    return 0;
}

数位dp(求1-n中数字1出现的个数),布布扣,bubuko.com

时间: 2024-12-28 09:09:06

数位dp(求1-n中数字1出现的个数)的相关文章

[ACM] hdu 3555 Bomb (数位DP,统计1-N中含有“49”的总数)

Bomb Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 131072/65536 K (Java/Others) Total Submission(s): 7187 Accepted Submission(s): 2512 Problem Description The counter-terrorists found a time bomb in the dust. But this time the terrorists impro

hdu3709 数位dp(自身平衡的数字)

http://acm.hdu.edu.cn/showproblem.php?pid=3709 Problem Description A balanced number is a non-negative integer that can be balanced if a pivot is placed at some digit. More specifically, imagine each digit as a box with weight indicated by the digit.

位操作(求[a, b] 中二进制位为1的个数最多的数)

传送门 题意:求区间[a, b]中二进制位为1的个数最多的那个数,如果存在多解,则输出最小的那个.(0 <= a <= b) 关键: 对一个数a可以利用 a | (a + 1) 来将a的二进制位中最低的0设置为1 附上代码: 1 #include <stdio.h> 2 3 typedef long long ll; 4 5 int main(void) { 6 int n; 7 scanf("%d", &n); 8 while (n-- > 0)

求排序数组中数字k出现的次数

思路:如果从头到尾遍历数组,那时间复杂度是O(n).我们可以利用题目给出的条件,由于是排序数组,我们可以利用二分查找来实现 时间复杂度为O(log2N) 具体代码如下: #include<iostream> #include<cassert> using namespace std; int findfirstk(int *ar, int len, int k, int start, int end)//利用二分查找找到第一个k出现的位置 { if(start > end)

求N!中的因子m的个数。

公式: [N/m] + [N/m2] + [N/m3] + ... (N/mx  != 0) 可以理解为[N/m]贡献了第一个m, 而[N/m2]在第一个个基础之上再贡献了一个m,以此类推. #include <stdio.h> #include <iostream> using namespace std; int cal(int n, int m) { int ret = 0; int t = m; while (n/t) { ret += n / t; t *= m; } r

2017年icpc西安网络赛 Maximum Flow (找规律+数位dp)

题目 https://nanti.jisuanke.com/t/17118 题意 有n个点0,1,2...n-1,对于一个点对(i,j)满足i<j,那么连一条边,边权为i xor j,求0到n-1的最大流,结果取模,n<=1e18 分析 可以写个最大流对数据找规律,但没找出来…… 然后只能取分析了,首先最大流等价于最小割 明确一定,0->n-1这个要先割掉 然后我们贪心,希望有一些点割掉与0相连的边,一些点割掉与n-1相连的边 我们去观察每个点与0相连和与n-1相连的两条边权值,容易发现

51Nod 1042 数字0-9的数量(数位DP)

题意: 求[l,r]中数字0-9分别出现的次数,11算两次1 思路: 数位dp题解好难写,直接贴代码吧 dp[i]表示[0, 10^i-1]中出现j的次数(按i位补全前导0,显然0-9出现的次数是相同的) 最后再减去每一位出现的前导零即可 代码: #include<iostream> #include<cstdio> #include<algorithm> #include<cmath> #include<cstring> #include<

有关动态规划(主要是数位DP)的一点讨论

动态规划(dynamic programming)是运筹学的一个分支,是求解决策过程(decision process)最优化的数学方法.20世纪50年代初美国数学家在研究多阶段决策过程的优化问题时,提出了最优化原理,把多阶段过程转化为一系列单阶段问题,利用各阶段之间的关系,逐个求解,创立了解决这类过程优化问题的新方法--动态规划. ——以上内容,节选自http://baike.so.com/doc/6995222-7218096.html <<<<<<<<

SPOJ MYQ10 10649. Mirror Number (数位dp)

SPOJ MYQ10 10649. Mirror Number (数位dp) ACM 题目地址:SPOJ MYQ10 Mirror Number 题意: 求[a,b]中镜像回文的个数. 0 <= a<=b <= 10^44 分析: 看到题目和数据范围就知道是数位dp了. 很明显镜像回文只有0,1,8,跟回文的一题一样,在dfs的时候得开个辅助数组记录前面已经选择的数字. 注意还得去掉前导0. 代码: /* * Author: illuz <iilluzen[at]gmail.com