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题目 我用的记 ...
随机推荐
- COJ 1211 大整数开平方
手写求大整数开根号所得到的值,具体计算过程参考别人的资料,最后利用java的大整数得到答案 别人博客链接:http://www.cnblogs.com/Rinyo/archive/2012/12/16 ...
- 简单的Fleury算法模板
假设数据输入时采用如下的格式进行输入:首先输入顶点个数n和边数m,然后输入每条边,每条边的数据占一行,格式为:u,v,表示从顶点u到顶点v的一条有向边 这里把欧拉回路的路径输出了出来: 手写栈: #i ...
- [Vijos] 弱弱的战壕
描述 永恒和mx正在玩一个即时战略游戏,名字嘛~~~~~~恕本人记性不好,忘了-_-b. mx在他的基地附近建立了n个战壕,每个战壕都是一个独立的作战单位,射程可以达到无限(“mx不赢定了?!?”永恒 ...
- msp430项目编程15
msp430中项目---简易红外遥控系统 1.红外工作原理 2.电路原理说明 3.代码(显示部分) 4.代码(功能实现) 5.项目总结 msp430项目编程 msp430入门学习
- POJ 3684 Physics Experiment
和蚂蚁问题类似. #include<cstdio> #include<cstring> #include<cmath> #include<vector> ...
- Spring中使用Log4j记录日志
以下内容引用自http://wiki.jikexueyuan.com/project/spring/logging-with-log4j.html: 例子: pom.xml: <project ...
- oracle dtrace for linux
https://docs.oracle.com/cd/E37670_01/E37355/html/ol_config_dtrace.html#
- java大文件的分割和合并
原文:http://www.open-open.com/code/view/1441679313430 import java.io.File; import java.io.FileInputStr ...
- python执行系统命令的几种方法
(1) os.system 这个方法是直接调用标准C的system() 函数,仅仅在一个子终端运行系统命令,而不能获取命令执行后的返回信息. import os os.system('cat /pro ...
- (void __user *)arg 中__user的作用
__user宏简单告诉编译器(通过 noderef)不应该解除这个指针的引用(因为在当前地址空间中它是没有意义的). (void __user *)arg 指的是arg值是一个用户空间的地址,不能直接 ...