1.HDU 4722 good numbers:
题意:给出一个区间【A,B】,求出区间内有多少个数的各位的和加起来模10等于0的数有多少个。
解法:这是一个数位DP简单入门题,简单的DFS+数组记忆化搜索就可以。姿势是自己写的。。感觉略搓,做到第三个数位DP题的时候看到了别人的姿势,学习了。
代码:
#include
#include
#include
#include
#include
#include
#include
//#include
#define N 22
using namespace std;
typedef pair PII;
const long long INF=0x3f3f3f3f;
void Open()
{
#ifndef ONLINE_JUDGE
freopen("D:/in.txt","r",stdin);
//freopen("D:/my.txt","w",stdout);
#endif // ONLINE_JUDGE
}
long long dit[N];
long long dp[N][N][3];
long long dfs(long long idx,long long mod,bool limit,long long edidx)
{
if(dp[idx][mod][limit]!=-1)
return dp[idx][mod][limit];
if(idx==edidx+1)
{
if(mod%10==0)
{
//cout<<1<
2.HDU 3555 Bomb
题意:"49"连在一起的数是good number,现在给你一个区间,让你找出区间中有多少个good number。
解法:仍然是一个简单数位DP,将上面一题的代码随便改改就可以过了。
代码:
#include
#include
#include
#include
#include
#include
#include
//#include
#define N 22
using namespace std;
typedef pair PII;
const long long INF=0x3f3f3f3f;
void Open()
{
#ifndef ONLINE_JUDGE
freopen("D:/in.txt","r",stdin);
//freopen("D:/my.txt","w",stdout);
#endif // ONLINE_JUDGE
}
long long dit[N];
long long dp[N][3][3][3];
long long dfs(long long idx,bool ppre,long long pre,bool limit,long long edidx)
{
if(dp[idx][ppre][pre][limit]!=-1)
return dp[idx][ppre][pre][limit];
if(idx==edidx+1)
{
if(ppre && pre == 1)
{
return dp[idx][ppre][pre][limit]=1;
}
return dp[idx][ppre][pre][limit]=0;
}
if(ppre && pre == 1)
{
long long cur=10;
if(limit){
int tmpidx=idx;
cur=dit[edidx-idx];
while(++tmpidx<=edidx)
{
cur*=10;
cur+=dit[edidx-tmpidx];
}
cur++;
}else{
int tmpidx=idx;
while(++tmpidx<=edidx)
{
cur*=10;
}
}
return dp[idx][ppre][pre][limit]=cur;
}
long long ret=0;
for(long long i=0;i <= (limit?dit[edidx-idx]:9);i++)
{
long long flag=0;
if(i==4) flag=2;
if(i==9) flag=1;
ret+=dfs(idx+1,pre==2,flag,limit && i==dit[edidx-idx],edidx);
}
return dp[idx][ppre][pre][limit]=ret;
}
long long getval(long long x)
{
long long ditnum=0;
memset(dp,-1,sizeof dp);
while(x)
{
dit[ditnum++]=x%10;
x/=10;
}
return dfs(1,0,0,1,ditnum);
}
int main()
{
Open();
long long T;
scanf("%I64d",&T);
while(T--)
{
long long a;
scanf("%I64d",&a);
printf("%I64d\n",getval(a));
}
return 0;
}
3.HDU 2089 不要62
题意:数字中有“4”或者“62”的数字是不吉利数字,仍然是给出一个区间,让我们求出有多少个吉利的数字。
解法:仍然是简单的数位DP。改改代码就过了。。
代码:
#include
#include
#include
#include
#include
#include
#include
//#include
#define N 22
using namespace std;
typedef pair PII;
const long long INF=0x3f3f3f3f;
void Open()
{
#ifndef ONLINE_JUDGE
freopen("D:/in.txt","r",stdin);
//freopen("D:/my.txt","w",stdout);
#endif // ONLINE_JUDGE
}
long long dit[N];
long long dp[N][4][4][2];
long long dfs(long long idx,bool ppre,long long pre,bool limit,long long edidx)
{
if(dp[idx][ppre][pre][limit]!=-1)
return dp[idx][ppre][pre][limit];
if(idx==edidx+1)
{
if((ppre && pre == 1) || pre==3)
{
//cout<<"1idx,ppre,pre,limit val "<
#include
#include
#include
#include
#include
#include
#include
//#include
#define N 21
using namespace std;
typedef pair PII;
const long long INF=0x3f3f3f3f;
void Open()
{
#ifndef ONLINE_JUDGE
freopen("D:/in.txt","r",stdin);
//freopen("D:/my.txt","w",stdout);
#endif // ONLINE_JUDGE
}
long long valA;
long long dit[N];
long long dp[N][11110];
long long dfs(long long idx,long long sum,bool limit)
{
if(sum<0) return 0;
if(idx == -1)
{
return sum>=0;
}
if(!limit && dp[idx][sum]!=-1)
return dp[idx][sum];
long long ret=0;
int ed=limit?dit[idx]:9;
for(long long i=0;i <= ed;i++)
{
ret+=dfs(idx-1,sum-i*(1<
题意:还是给出一个区间【A,B】,求出区间内有多少个数x满足 X mod f(X) ==0。其中F(x)表示X十进制表示下的各位数位的数的和。
解法:此题与前四个题目比起来难了一些。在这里DFS的方法并不好想,所以用了数位DP直推的方法写。定义dp[len][i][j][k];表示len位的数 F(x)==i 的数模 j 的结果为k的数有多少个。这样的话,我们首先预处理出dp数组。递推方程式比较容易出的。然而问题是预处理了dp数组之后我们该怎么得到结果。
具体见代码注释:
#include
#include
#include
#include
#include
#include
#include
//#include
#define N 11
using namespace std;
typedef pair PII;
const int INF=0x3f3f3f3f;
void Open()
{
#ifndef ONLINE_JUDGE
freopen("D:/in.txt","r",stdin);
//freopen("D:/my.txt","w",stdout);
#endif // ONLINE_JUDGE
}
int valA;
int dit[N];
//int dp[N][4][4][2];
int dp[N][91][91][91];//dp[len][i][j][k]前len位数和为i模j结果为k的数的个数
void init()
{
for(int i=1;i<=81;i++)
dp[0][0][i][0]=1;
for(int len=0;len<9;len++)
for(int i=0;i<=9*len;i++)
for(int j=1;j<=81;j++)
for(int k=0;k=0;i--)//遍历x的各个数位。
{
int ret=0;
for(int j=0;j