BZOJ 4521 手机号码

SB数位dp.

我的貌似要特判9999999999的情况。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
long long l,r,dp[13][4][10][2][2][2],ret=0,bit[15];
void reset()
{
    for (long long i=0;i<=11;i++)
        for (long long j=0;j<=3;j++)
            for (long long k=0;k<=9;k++)
                for (long long l=0;l<=1;l++)
                    for (long long a=0;a<=1;a++)
                        for (long long b=0;b<=1;b++)
                            dp[i][j][k][l][a][b]=-1;
}
void get_bit(long long x)
{
    ret=0;
    while (x) {bit[++ret]=x%10;x/=10;}
}
long long dfs(long long pos,long long cnt,long long num,long long f,long long f1,long long f2,bool flag)
{
    if (!pos) return f;
    if ((!flag) && (dp[pos][cnt][num][f][f1][f2]!=-1)) return dp[pos][cnt][num][f][f1][f2];
    long long ans=0,up=flag?bit[pos]:9,tc;
    for (long long i=0;i<=up;i++)
    {
        if ((i==4) && (f2)) continue;
        if ((i==8) && (f1)) continue;
        if (i==num) tc=min(cnt+1,3LL);else tc=1;
        ans+=dfs(pos-1,tc,i,f|(tc==3),f1|(i==4),f2|(i==8),flag&&(i==up));
    }
    if (!flag) dp[pos][cnt][num][f][f1][f2]=ans;
    return ans;
}
long long ask(long long x)
{
    get_bit(x);
    if (x==9999999999LL) return dfs(ret,1,0,0,0,0,1);
    else return dfs(ret,0,-1,0,0,0,1);
}
int main()
{
    scanf("%lld%lld",&l,&r);reset();
    printf("%lld\n",ask(r)-ask(l-1));
    return 0;
}
时间: 2024-09-29 23:58:50

BZOJ 4521 手机号码的相关文章

BZOJ 4521 CQOI 2016 手机号码 数位DP

4521: [Cqoi2016]手机号码 Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 539  Solved: 325[Submit][Status][Discuss] Description 人们选择手机号码时都希望号码好记.吉利.比如号码中含有几位相邻的相同数字.不含谐音不 吉利的数字等.手机运营商在发行新号码时也会考虑这些因素,从号段中选取含有某些特征的号 码单独出售.为了便于前期规划,运营商希望开发一个工具来自动统计号段中满足特征的号码

bzoj 4521: [Cqoi2016]手机号码

感觉get到了一种数位dp的新姿势,加一位表示当前要填的数有没有限制(感觉以前的写法都太蠢了). 这么写有两个地方要注意: 1.每dp到一位时需要f[i][初始状态]++,相当于这位前都是前导零(这道题我把前两位填了两个10作为初始状态). 2.因为有了1,所以初始状态后的第一位不能填0,需要特判 f[i][j][k][l][p][q][o]表示填到第几位,上上位和上位分别是什么,4,8是否出现过,三个连续的是否出现过,以及当前位是否有限制. #include<iostream> #inclu

[DynamicProgramming]动态规划题目泛做

Educational Codeforces Round 12 F 大意: 求n(n<=1011)以内恰好有4个因数的数的个数 分析: 首先一个数恰好有4个因数,说明它质因数分解之后是两个质数的乘积或是一个质数的三次方,对于后一种情况我们直接n1/3就能算出来,关键在于计算n以内有多少个数是两个素数的乘积. 设n=p1?p2,则必然有p1<n?√,p2>n?√,我们枚举p1,那么问题就在于np1 内有多少个素数. 这一点我们用dp来解决. 记pj为第j个素数,dp[n][j]为[1,n]

4521: [Cqoi2016]手机号码|数位DP

数据范围这么小..感觉暴力可过啊.. DP也是随便设计状态 F[i][j][k][s][l] 表示前i位,最后一位是j 最后一位连续出现k次(如果k已经等于3那么就一直不变)s表示4,8的出现状态 l表示前缀是否和原数的前缀相同 转移就是枚举下一位转移,也很简单.. #include<algorithm> #include<iostream> #include<cstdlib> #include<cstring> #include<cstdio>

bzoj4521【CQOI2016】手机号码

4521: [Cqoi2016]手机号码 Time Limit: 10 Sec  Memory Limit: 512 MB Submit: 382  Solved: 238 [Submit][Status][Discuss] Description 人们选择手机号码时都希望号码好记.吉利.比如号码中含有几位相邻的相同数字.不含谐音不 吉利的数字等.手机运营商在发行新号码时也会考虑这些因素,从号段中选取含有某些特征的号 码单独出售.为了便于前期规划,运营商希望开发一个工具来自动统计号段中满足特征的

【BZOJ-4521】手机号码 数位DP

4521: [Cqoi2016]手机号码 Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 303  Solved: 194[Submit][Status][Discuss] Description 人们选择手机号码时都希望号码好记.吉利.比如号码中含有几位相邻的相同数字.不含谐音不吉利的数字等.手机运营商在发行新号码时也会考虑这些因素,从号段中选取含有某些特征的号码单独出售.为了便于前期规划,运营商希望开发一个工具来自动统计号段中满足特征的号码数量

【luogu4124】【bzoj4521】 [CQOI2016]手机号码 [数位dp]

P4124 [CQOI2016]手机号码 4521 这道题要注意卡上下界 我错了 写dfs版的更好考虑状态 写纯方程转移那个细节把我想瓜了 1 #include<iostream> 2 #include<cstdio> 3 #include<queue> 4 #include<cstring> 5 #include<cmath> 6 #include<stack> 7 #include<algorithm> 8 using

BZOJ 1013: [JSOI2008]球形空间产生器sphere

二次联通门 : BZOJ 1013: [JSOI2008]球形空间产生器sphere /* BZOJ 1013: [JSOI2008]球形空间产生器sphere 高斯消元 QAQ SB的我也能终于能秒题了啊 设球心的坐标为(x,y,z...) 那么就可以列n+1个方程,化化式子高斯消元即可 */ #include <cstdio> #include <iostream> #include <cstring> #define rg register #define Max

bzoj 3309 DZY Loves Math - 莫比乌斯反演 - 线性筛

对于正整数n,定义f(n)为n所含质因子的最大幂指数.例如f(1960)=f(2^3 * 5^1 * 7^2)=3, f(10007)=1, f(1)=0. 给定正整数a,b,求sigma(sigma(f(gcd(i,j)))) (i=1..a, j=1..b). Input 第一行一个数T,表示询问数. 接下来T行,每行两个数a,b,表示一个询问. Output 对于每一个询问,输出一行一个非负整数作为回答. Sample Input 4 7558588 9653114 6514903 445