hdu3652(含有13且能被13整除的数)数位DP基础
B-number
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 3257 Accepted Submission(s): 1819
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 is to calculate how many wqb-numbers from 1 to n for a given
integer n.
100
200
1000
1
2
2
#include<iostream>
#include<cstdio>
#include<cstring> using namespace std; const int N=;
int md[N],dp[N][][]; void Init(){
md[]=;
for(int i=;i<N;i++)
md[i]=md[i-]*;
memset(dp,,sizeof(dp));
dp[][][]=;
for(int i=;i<N-;i++)
for(int j=;j<;j++){
for(int k=;k<;k++)
dp[i+][(j+md[i]*k)%][]+=dp[i][j][];
dp[i+][(j+md[i])%][]-=dp[i][j][];
dp[i+][(j+md[i]*)%][]+=dp[i][j][];
dp[i+][(j+md[i])%][]+=dp[i][j][];
for(int k=;k<;k++)
dp[i+][(j+md[i]*k)%][]+=dp[i][j][];
}
}
int solve(int x)
{
int s[],len=,xx=x;
while(x>)
{
s[++len]=x%;
x/=;
}
s[len+]=; //初始化前缀为0,0是没有任何影响的,后面一位可能会用到前面一位
// cout<<len<<endl;
int ans=,flag=;
int yy=,yyy=;
int answer;
for(int i=len;i>=;i--) //每次枚举的数是:上界前缀+i这一位的数字+符合要求的dp[i][j][k]
{
answer=ans;
for(int kk=;kk<s[i];kk++)
{ for(int j=;j<;j++)
{
if(( (yyy*+ kk)*md[i-] +j)%==) //i这一位上枚举的数字变化,就得判断
{
ans+=dp[i-][j][];
}
} }
if(flag) //如果前缀中有出现13,并且
{
// ans+=s[i]*dp[i-1][0];
for(int kk=;kk<s[i];kk++)
for(int j=;j<;j++)
{
if(( (yyy*+ kk)*md[i-] +j)%==)
{
ans+=dp[i-][j][];
}
}
}
//只考虑以len位置为i的开头的数
if(!flag && s[i]>)
{
// ans+=dp[i-1][1];//因为是大于号,所以低一位可以完全枚举,加上首位为3的个数
for(int j=;j<;j++)
{
if(( (yyy*+ )*md[i-] +j)%==)
{
ans+=dp[i-][j][];
}
}
}
//考虑前缀的影响
if(!flag && s[i+]== && s[i]>)
// ans+=dp[i][1];
{
for(int j=;j<;j++)
{
if(( ((yyy-s[i+]+)*+ )*md[i-] + j )%==)
{
ans+=dp[i-][j][];
}
}
}
if(s[i+]== && s[i]==)
{
flag=;
}
yyy=yyy*+s[i];
}
return ans;
}
int main(){ // freopen("test.txt","r",stdin);
//cout<<(0%13)<<endl;
Init();
int n;
while(~scanf("%d",&n)){
printf("%d\n",solve(n+));
}
return ;
}
小优化的代码:
已知(a+b)%13=0,已知a,求b;
1:(a+b)%13=0;
2:(a%13+b%13)%13=0;
3:(13-a%13)%13=b;(第二次再MOD13,是因为a有可能等于0)
#include<iostream>
#include<cstdio>
#include<cstring> using namespace std;
const int V=; const int mod=;
const int N=;
int md[N],dp[N][][]; void Init(){
md[]=;
for(int i=;i<N;i++)
md[i]=md[i-]*%;
memset(dp,,sizeof(dp));
dp[][][]=;
for(int i=;i<N-;i++)
for(int j=;j<;j++){
for(int k=;k<;k++)
dp[i+][(j+md[i]*k)%][]+=dp[i][j][];
dp[i+][(j+md[i])%][]-=dp[i][j][];
dp[i+][(j+md[i]*)%][]+=dp[i][j][];
dp[i+][(j+md[i])%][]+=dp[i][j][];
for(int k=;k<;k++)
dp[i+][(j+md[i]*k)%][]+=dp[i][j][];
}
} int solve(int x)
{
int s[],len=,xx=x;
while(x>)
{
s[++len]=x%;
x/=;
}
s[len+]=; //初始化前缀为0,0是没有任何影响的,后面一位可能会用到前面一位
// cout<<len<<endl;
int ans=,flag=;
int yy=,yyy=;
int answer;
for(int i=len;i>=;i--)
{
// ans+=(s[i]*dp[i-1][2]); //含4和62的个数
answer=ans;
int temp_mod;
for(int kk=;kk<s[i];kk++)
{
temp_mod = ( - ( (yyy * + kk) * md[i-] )% ) %;
ans+=dp[i-][temp_mod][] ;
if(flag) //如果前缀中有出现13,并且
ans+=dp[i-][temp_mod][];
if(!flag && kk==)
{
ans+=dp[i-][temp_mod][];
}
if(!flag && s[i+]== && kk==)
ans+=dp[i-][temp_mod][]; }
//只考虑以len位置为i的开头的数
if(s[i+]== && s[i]==)
{
flag=; }
yyy=yyy*+s[i];
// printf("%d\n",ans-answer);
}
return ans;
} int main()
{ // freopen("test.txt","r",stdin);
//cout<<(0%13)<<endl;
Init();
int n;
while(~scanf("%d",&n)){
printf("%d\n",solve(n+));
}
return ;
}
hdu3652(含有13且能被13整除的数)数位DP基础的更多相关文章
- CF .Beautiful numbers 区间有多少个数字是可以被它的每一位非零位整除。(数位DP)
题意:数字满足的条件是该数字可以被它的每一位非零位整除. 分析:大概的思路我是可以想到的 , 但没有想到原来可以这样极限的化简 , 在数位dp 的道路上还很长呀 : 我们都知道数位dp 的套路 , 核 ...
- HDU 3652 区间有13并且这样整除13 的数量(数位DP)
题目:求1-n的范围里含有13且能被13整除的数字的个数. 分析: dfs(len, num, mod, flag) mod记录数字对13取余后的值 len表示当前位数 num==0 不含13且上一位 ...
- HDU3652 B-number —— 数位DP
题目链接:https://vjudge.net/problem/HDU-3652 B-number Time Limit: 2000/1000 MS (Java/Others) Memory L ...
- 数位DP HDU3652
B-number Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Su ...
- hdu3652(数位dp)
题目连接:http://acm.hdu.edu.cn/showproblem.php?pid=3652 题意:求1~n含有13且能被13整除的数的个数. 分析:数位dp,dp数组加一维来维护到pos位 ...
- 【Hdu3652】B-number(数位DP)
Description 题目大意:求小于n是13的倍数且含有'13'的数的个数. (1 <= n <= 1000000000) Solution 数位DP,题目需要包含13,且被13整除, ...
- [Hdu3652]B-number(数位DP)
Description 题目大意:求小于n是13的倍数且含有'13'的数的个数. (1 <= n <= 1000000000) Solution 数位DP,题目需要包含13,且被13整除, ...
- 【HDU3652】B-number 数位DP
B-number Problem Description A wqb-number, or B-number for short, is a non-negative integer whose de ...
- hdu3652 B-number 数位DP
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3652 题意就是求区间内能被13整除并且包含”13“的数字的个数 感觉是比较中等的数位DP题目 我用的记 ...
随机推荐
- JPA框架下使用纯粹的原生SQL
最近遇到一个需求,查询数据库中对应表的字段是动态的,项目使用的框架使用JPA+Spring Boot,JPA自带原生SQL支持的传入参数是强类型的,无法用于查询语句的字段更改,因为插入字符串的话带有单 ...
- php 之mysql安全
php 之mysql安全 原文:https://www.cnblogs.com/mafeng/p/5939329.html. 请浏览原文. 一.服务器配置方面. (1) 打开php的安全模式 php的 ...
- Git学习之常见错误 clone被拒绝
Git学习之常见错误 问题: git clone 时 报错 Permission Denied (权限被拒绝). 解决方法: 需要把本地的公钥上传到服务器. 解决步骤: ①第一步,设置本地的git的用 ...
- HDU 1669 二分图多重匹配+二分
Jamie's Contact Groups Time Limit: 15000/7000 MS (Java/Others) Memory Limit: 65535/65535 K (Java/ ...
- [bzoj4199][Noi2015]品酒大会_后缀自动机_后缀树_树形dp
品酒大会 bzoj-4199 Noi-2015 题目大意:给定一个字符串,如果其两个子串的前$r$个字符相等,那么称这两个子串的开头两个位置$r$相似.如果两个位置勾兑在一起那么美味度为两个位置的乘积 ...
- 一次使用NodeJS实现网页爬虫记
前言 几个月之前,有同事找我要PHP CI框架写的OA系统.他跟我说,他需要学习PHP CI框架,我建议他学习大牛写的国产优秀框架QeePHP. 我上QeePHP官网,发现官方网站打不开了,GOOGL ...
- 蓦然回首,Java 已经 24 岁了!
01.蓦然 真没想到,Java 竟然 24 岁了(算是 90 后)! 提起 Java,印象最深刻的当然就是: class Cmower { public static void main(Strin ...
- 是男人就下100层【第四层】——Crazy贪吃蛇(2)
在上一篇<是男人就下100层[第四层]--Crazy贪吃蛇(1)>中我们让贪吃蛇移动了起来,接下来我们来实现让贪吃蛇能够绕着手机屏幕边线移动而且能够改变方向 一.加入状态并改动代码 首先我 ...
- centos编辑界面和图形界面登陆切换设置
输入命令 vi /etc/inittab 到最后一行.把5改成3 保存退出. 各数字的含义: # 0 - halt (Do NOT set initdefault to this) ...
- cocos2dx 制作单机麻将(五)
cocos2dx 制作单机麻将(五) 麻将逻辑6 最基础的4人麻将逻辑(轮流循环出牌, 之前学的都能用上 跑起来了!!!) 最基础的麻将逻辑 依据自己须要 设置麻将人数GAME_PLAYER 基本流 ...