codeforces 204A A. Little Elephant and Interval(dp+组合数学)

题目链接:

codeforces 204A


题目大意:

给出一个l和r,求取在l和r之间的首尾相同的数的个数。


题目分析:

  • 按位进行统计,计算出不大于某一个数的所有的合法的情况。然后可以利用这个前缀和求取区间和。
  • 按位统计的时候,首先特判数的长度为1位和两位的情况,分别是10和9,如果当前数就是1位,那么就是这个数的大小,其他具体细节见代码.
  • 然后就是统计所有不足位的情况,也就是数的长度不到给定数长度的情况,不足位的数一定小于给定数,所以直接固定首尾,结果加上10n?2即可。
  • 足位的情况,就是枚举每一位,然后如果当前枚举为小于给定数数位上的数,那么后面可以随便放置,所以有10n?i?1种情况,当前位等于给定数位上的数的时候,当前先不能判断,等后面能够确定时统计结果。

AC代码:

#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#define MAX 27

using namespace std;

typedef long long LL;

char l[MAX],r[MAX];
LL dp[MAX],pp[MAX];

void init ( )
{
    pp[0] = 1;
    for ( int i = 1 ; i < MAX ;i++ )
        pp[i] = pp[i-1]*10LL;
}

LL solve ( char s[] )
{
    LL ret = 0;
    int n = strlen ( s );
    if ( n > 1 ) ret += 10;
    else ret += s[0]-48+1;
    if ( n > 2 ) ret += 9;
    for ( int i = 1; i < n-2 ;i++ )
        ret += 9LL*pp[i];
    for ( int i = 0 ; i < n-1; i++ )
    {
        int x = s[i]-48;
        if ( i == 0 ) x--;
        ret += x*pp[n-2-i];
    }
    if ( n > 1 && s[n-1] >= s[0] ) ret++;
    return ret;
}

int main ( )
{
    init ( );
    while ( ~scanf ( "%s%s" , l , r ) )
    {
        //cout << solve( r ) << " " << solve ( l ) << endl;
        int n = strlen ( l );
        printf ( "%I64d\n" , solve ( r ) - solve(l) + ( l[n-1] == l[0]?1LL:0LL) );
    }
}

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-08-24 07:33:16

codeforces 204A A. Little Elephant and Interval(dp+组合数学)的相关文章

codeforces 161D - Distance in Tree(树形dp)

题目大意: 求出树上距离为k的点对有多少个. 思路分析: dp[i][j] 表示 i 的子树中和 i 的距离为 j 的点数有多少个.注意dp[i] [0] 永远是1的. 然后在处理完一颗子树后,就把自身的dp 更新. 更新之前更新答案. 如果这颗子树到 i 有 x 个距离为j的.那么答案就要加上 dp[i] [ k-j-1] * x; #include <iostream> #include <cstdio> #include <cstring> #include &l

Codeforces 437E The Child and Polygon(区间DP)

题目链接:Codeforces 437E The Child and Polygon 题目大意:给出一个多边形,问说有多少种分割方法,将多边形分割为多个三角形. 解题思路:首先要理解向量叉积的性质,一开始将给出的点转换成顺时针,然后用区间dp计算.dp[i][j]表示从点i到点j可以有dp[i][j]种切割方法.然后点i和点j是否可以做为切割线,要经过判断,即在i和j中选择的话点k的话,点k要在i,j的逆时针方. #include <cstdio> #include <cstring&g

Codeforces 219D. Choosing Capital for Treeland (树dp)

题目链接:http://codeforces.com/contest/219/problem/D 树dp 1 //#pragma comment(linker, "/STACK:102400000, 102400000") 2 #include <algorithm> 3 #include <iostream> 4 #include <cstdlib> 5 #include <cstring> 6 #include <cstdio&

CodeForces Round#229 DIV2 C 递推DP

对这道题目也只好说呵呵了,没注意k的范围最大才10,所以昨晚纠结了很久,没什么好的方法来处理,后来无奈想去翻翻题解,发现人家开头就来了句,因为k的范围比较小 所以.........我只好暂停马上回头看看题目,是的,k比较小所以完全可以先在询问前预处理DP一遍, DP就比较清晰了,dp[i][j]  (i>=0 && i<k,,,,j>=i && j <=n)代表意义呢 以i为开头的  区间[1,j]注意 是 1~j的 所需要的操作数,题目问的是最小操

codeforces 235B Let&#39;s Play Osu! 概率dp

题意:给定n表示有n个格子,下面每个格子为O的概率是多少.对于一段连续 x 个O的价值就是 x^2 ;求获得的价值的期望是多少. 思路:n^2=n×(n-1)+n,设ai为第i段连续O的长度,∑ai^2 = ∑[ ai+ ai*(ai-1) ] = ∑ ai*(ai-1) + ∑ai = ∑ C(ai, 2)*2 + ∑ai,那么问题可以转 化为求长度大于1的连续段数*2+O的个数的总期望. ∑ai我们可以理解为O的总个数,所以它的期望为∑pi: C(ai, 2)*2我们可以认 为是连续ai个O

Codeforces 235B Let&#39;s Play Osu! (概率dp求期望+公式变形)

B. Let's Play Osu! time limit per test:2 seconds memory limit per test:256 megabytes You're playing a game called Osu! Here's a simplified version of it. There are n clicks in a game. For each click there are two outcomes: correct or bad. Let us deno

Codeforces 235B Let&#39;s Play Osu! 概率dp(水

题目链接:点击打开链接 给定n表示有n个格子 下面每个格子为O的概率是多少. 对于一段连续 x 个O的价值就是 x*x ; 问: 获得的价值的期望是多少. 思路: 把公式拆一下.. #include <cstdio> const int N = 100005; double dp[N][2], p[N]; int main(){ int n; scanf("%d", &n); for(int i = 1; i <= n; i ++) { scanf("

[Codeforces 1295F]Good Contest(DP+组合数学)

[Codeforces 1295F]Good Contest(DP+组合数学) 题面 有一个长度为\(n\)的整数序列,第\(i\)个数的值在\([l_i,r_i]\)中随机产生.问这个序列是一个不上升序列的概率(模\(998244353\)意义下). \(n \leq 50,l_i,r_i \leq 998244351\) 分析 和[APIO2016]划艇几乎一模一样.可惜比赛的时候时间不够. 首先把问题转化成求最长不上升序列的数量. 我们把这些区间离散化,分割成两两之间不互相覆盖的若干个区间

CodeForces 204A Little Elephant and Interval 数位DP

#include <cstdio> #include <cstring> using namespace std; typedef __int64 LL; int a[33]; LL dp[33][10]; LL dfs(int x, int s, int e, int flag, int first) { if(x == -1) return s == e; if(!flag && dp[x][s]!= -1) return dp[x][s]; int end =