题目链接:点击查看

题目大意:给出平衡数的定义:每一个偶数出现的次数必须是奇数次,每一个奇数出现的次数必须是偶数次,求给定区间中有多少个平衡数

题目分析:数位dp,这个题目就难在怎么确定状态转移,本来我看错题目了,以为只要有奇数个偶数和偶数个奇数就行,但还是想的太简单了,看了网上大佬们的题解才知道,原来我们可以把每一个数字的状态压缩,每一个数字都有三种状态:0表示没出现过,1表示出现了奇数次,2表示出现了偶数次,普通的状态压缩都是0和1的两种状态,这个题有三种状态,所以我们用三进制来储存就好了,三的11次方没超过60000,所以dp数组开dp[20][60000]就好,dp[i][j]代表在第i位,状态位j时的符合条件的数量,在转移状态的时候我用到了一个change函数,具体怎么实现的非常巧妙,也算是学到了进制转换的一点小技巧,假如想修改第i位上的数字时(从右向左的第i个),我们需要先得到第i位上的数字是多少,常规操作是先一直除3,直到让第i位变成当前的个位,然后对3取模即可,如果想增加的话也是需要加三的i次方,听起来好像已经很简单了,但是却有更简单的方法,就是利用一个辅助数组f储存3的i次方(1<=i<=10),然后用表示状态的数对f[i+1]取余先令其范围变为0~f[i+1],然后在继续除以f[i],就可以直接获得第i位上的数了,具体的看代码吧:

#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<algorithm>
#include<stack>
#include<queue>
#include<map>
#include<cmath>
#include<sstream>
using namespace std;typedef long long LL;const int inf=0x3f3f3f3f;const int N=20; LL dp[N][60000];//dp[pos][sta]int b[N];int f[N];//储存3的i次方bool check(int sta)
{for(int i=0;i<=9;i++,sta/=3){if((i&1)&&sta%3==1)return false;if(!(i&1)&&sta%3==2)return false;}return true;
}int change(int sta,int i)
{int x=(sta%f[i+1])/f[i];//获得第i位上的数if(x==2)return sta-f[i];elsereturn sta+f[i];
}LL dfs(int pos,int sta,bool lead,bool limit)
{if(pos==-1)return check(sta);if(!limit&&dp[pos][sta]!=-1)return dp[pos][sta];LL ans=0;int up=limit?b[pos]:9;for(int i=0;i<=up;i++){if(lead&&i==0)ans+=dfs(pos-1,0,true,limit&&i==b[pos]);elseans+=dfs(pos-1,change(sta,i),false,limit&&i==b[pos]);}if(!limit)dp[pos][sta]=ans;return ans;
}LL solve(LL n)
{int cnt=0;while(n){b[cnt++]=n%10;n/=10;}return dfs(cnt-1,0,true,true);
}int main()
{
//  freopen("input.txt","r",stdin)int w;cin>>w;f[0]=1;for(int i=1;i<=10;i++)f[i]=f[i-1]*3;   memset(dp,-1,sizeof(dp));while(w--){LL a,b;scanf("%lld%lld",&a,&b);printf("%lld\n",solve(b)-solve(a-1));}return 0;
}

SPOJ - BALNUM Balanced Numbers(数位dp+进制转换)相关推荐

  1. spoj Balanced Numbers(数位dp)

    一个数字是Balanced Numbers,当且仅当组成这个数字的数,奇数出现偶数次,偶数出现奇数次 一下子就相到了三进制状压,数组开小了,一直wa,都不报re, 使用记忆化搜索,dp[i][s] 表 ...

  2. Balanced Numbers数位dp

    三进制搞下, 0  表示没出现过,  第i位为1 表示 i出现了奇数次,  2表示i 出现了偶数次. #include <cstdio> #include <cstring> ...

  3. CodeForces - 1249C2 Good Numbers (hard version)(进制转换)

    题目链接:点击查看 题目大意:给出一个数n,求出一个大于等于n的"好数","好数"的规定是只由3的幂次之和构成 题目分析:直接将n拆成三进制,然后贪心从最高位开 ...

  4. 探索C/C++ 进制转换之美:从原理到应用

    一.简介 (Introduction) 进制 前缀表示 整数常量示例 转换库接口 参数及返回值示例 二进制 0b 或 0B 0b1010 std::bitset<> std::bitset ...

  5. zzuli 2134: 维克兹的进制转换 (DP)@

    2134: 维克兹的进制转换 Time Limit: 1 Sec   Memory Limit: 128 MB Submit: 156   Solved: 18 Submit Status Web B ...

  6. 单片机进制转换实现(报告+源码)

    用4x4矩阵及LCD1602液晶显示实现各进制转换 摘要:在计算机及其相关的各领域中,数制的二进制.八进制.十进制和十六进制之间的相互转换可谓无处不在.为满足相关领域人员对进制转换计算的需求,特此利用 ...

  7. 计算机中的数制和编码教案,计算机《数制与编码进制转换》公开课教案.doc

    <计算机应用基础>教案 新田县职业中学 蒋玲 PAGE PAGE 7 数制与编码--进制转换 [学情分析]本课内容是在学生已经学习了计算机发展与应用.计算机系统的组成等知识的基础上进行,已 ...

  8. 生成大小写字母加数字混合ID与自定义进制转换

    有时候可以在别的网站上看到类似于这样的ID : D6pPMSTjOFI, 关于数据库主键的选择园子里面也讨论过许多了,比如这篇 小议数据库主键选取策略(原创). 字符串作ID有时候还是有它的优点的,但 ...

  9. C语言取字节的第n二进制,学C语言的看过来,最完整进制转换、整数和小数内存存储模型...

    什么是进制 进制也就是进位计数制,是人为定义的带进位的计数方法.对于任何一种进制---N进制,就表示每一位置上的数运算时都是逢N进一位. 数数相信大家都会了,比如0 1 2 3 4 5 6 7 8 9 ...

最新文章

  1. linux lua 交叉编译,交叉编译 XXX含义与作用
  2. RedHat Enterprise Linux6.4 使用CentOS yum
  3. 把Java程序打包成jar文件包并执行
  4. kvm直通sata_基于KVM的SRIOV直通配置及性能测试
  5. 如何使用Nginx服务开启HTTP2
  6. go 类型断言_深入理解Go的interface内部执行原理
  7. Debug日志正常,输出和HTML页面乱码
  8. 经典排序算法(十五)--耐心排序Patience Sorting
  9. Qt项目--截屏软件
  10. 概念数据模型到逻辑数据模型的转化
  11. MLX90614修改地址
  12. 计算机网络上有个红叉没无线,如果计算机的无线网络上出现红叉指示连接不正确,该怎么办| WIFI显示红叉...
  13. 中国传统文化-雨课堂期末2022
  14. mysql数据库应用经典案例_MySQL数据库“十宗罪”(十大经典错误案例)
  15. 苹果电脑MACbookAir快捷键大全
  16. Kerberos (一) --------- Kerberos 部署
  17. linux 多wan口 路由器,真假多WAN负载均衡
  18. Netty时间轮源码解析
  19. Microservices--原文翻译(英汉对照)
  20. 成功解决NotFoundError (see above for traceback): Failed to create a directory: ; No such file or directo

热门文章

  1. 并发的发展历史-集成电路和多道程序设计
  2. BeanFactory作为 IoC 容器示例
  3. CAS单点登录 - 创建用户会话、全局门票、临时票据
  4. 注解_自定义注解_格式本质
  5. AOP日志-后置通知
  6. 登陆状态下加入购物车
  7. RedisRDB持久化机制
  8. Hmac - Java加密与安全
  9. Spring Security OAuth2源码解析(三)——单点登录。
  10. python socket清空接受区_用Python制作只属于你和ta的聊天渠道吧