http://acm.hdu.edu.cn/showproblem.php?pid=3555
过年了…好懒…坎坷的回家….拜年…走亲戚…balabala…..玩了几天…然后..为了不影响进度….把插头DP跳过去了…(好懒….
第一道数位DP
感觉这个数位DP就是找到每一个数位的状态的个数,然后通过遍历这个数来找到题目需要的状态的答案
题意:给一个n,输出1~n里含有 49子序列的数的数量
思路: 最基础的数位DP,先找到每一位三种状态的数量,然后通过枚举N来找到答案
#include<map>
#include<set>
#include<queue>
#include<stack>
#include<math.h>
#include<string>
#include<vector>
#include<stdio.h>
#include<string.h>
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long LL;
#define maxn 1005
#define f(x) (x*1.0)
#define inf 0x3f3f3f3f
#define maxm maxn*maxn
#define min(a,b) (a>b?b:a)
#define max(a,b) (a>b?a:b)
#define lowbit(x) (x&(-x))
#define cheak(i) printf("%d ",i)
#define lson(x) (splay[x].son[0])
#define rson(x) (splay[x].son[1])
#define rfor(i,a,b) for(i=a;i<=b;++i)
#define lfor(i,a,b) for(i=a;i>=b;--i)
#define mem(a,b) memset(a,b,sizeof(a))
#define mec(a,b) memcpy(a,b,sizeof(b))
LL dp[25][3];
//0 不含有49的个数
//1 不含有49但最高位是9的个数
//2 含有49的个数
void init()
{
//寻找每一个状态在每一位的个数
dp[0][0]=1;
dp[0][1]=dp[0][2]=0;
int i;
rfor(i,1,25)
{
dp[i][0]=dp[i-1][0]*10-dp[i-1][1];
dp[i][1]=dp[i-1][0];
dp[i][2]=dp[i-1][2]*10+dp[i-1][1];
}
}
LL A[25];
LL solve(LL n)
{
int len=0,i;
LL ans=0;
while(n)
{
A[++len]=n%10;
n/=10;
}
A[len+1]=0;//这一步是防止上次输入对这次造成影响
bool flag=false;
lfor(i,len,1)//从高位到地位遍历
{
ans+=dp[i-1][2]*A[i];
if(flag) ans+=dp[i-1][0]*A[i];
else if(A[i]>4) ans+=dp[i-1][1];
if(A[i+1]==4&&A[i]==9) flag=true;
}
if(flag) ans++;
return ans;
}
int main()
{
int T;
LL n;
init();
scanf("%d",&T);
while(T--)
{
scanf("%lld",&n);
printf("%lld\n",solve(n));
}
return 0;
}
本文介绍了一种使用数位动态规划解决特定数值模式问题的方法,即计算1到n范围内所有包含49子序列的整数数量。通过预计算不同状态的数位个数,并结合枚举目标值n的每一位,最终得出问题的解答。
481

被折叠的 条评论
为什么被折叠?



