HDU 2089
区间[n,m],求n到m中没有“62”和“4”的数的个数
方法有很多,最简单的一种是dp[i][j] 表示第i位为j的解个数。
#include <bits/stdc++.h>
using namespace std;
int n,m,dp[10][10];
int d[10];
void init()
{
memset(dp,0,sizeof(dp));
dp[0][0]=1;
for(int i=1; i<=7; i++)
{
for(int j=0; j<=9; j++)
for (int k=0; k<=9; k++)
{
if(j!=4 && !(j==6 && k==2))
{
dp[i][j]+=dp[i-1][k];
}
}
}
}
int solve(int x)
{
int re=0;
memset(d,0,sizeof(d));
int len=0;
while(x>0)
{
d[++len] = x%10;
x/=10;
}
for(int i=len; i>=1; i--)
{
for(int j=0; j<d[i]; j++)
if(j!=4 && !(j==2 && d[i+1]==6))
{
re+=dp[i][j];
}
if(d[i]==4 || (d[i]==2 && d[i+1]==6)) break;
}
return re;
}
int main()
{
//freopen("in.txt","r",stdin);
init();
while(~scanf("%d %d",&n,&m))
{
if(m==0) break;
printf("%d\n",solve(m+1)-solve(n));
}
return 0;
}
小于n 的数中 含有49的数的个数
直接改上一题的两个数,换ll就可以。 然而还有很多其他的dp方法
复制网上的:
DP的状态是2维的dp[len][3]dp[len][0] 代表长度为len不含49的方案数dp[len][1] 代表长度为len不含49但是以9开头的数字的方案数dp[len][2] 代表长度为len含有49的方案数状态转移如下dp[i][0] = dp[i-1][0] * 10 - dp[i-1][1]; // not include 49 如果不含49且,在前面可以填上0-9 但是要减去dp[i-1][1] 因为4会和9构成49dp[i][1] = dp[i-1][0]; // not include 49 but starts with 9 这个直接在不含49的数上填个9就行了dp[i][2] = dp[i-1][2] * 10 + dp[i-1][1]; // include 49 已经含有49的数可以填0-9,或者9开头的填4接着就是从高位开始统计在统计到某一位的时候,加上 dp[i-1][2] * digit[i] 是显然对的,因为这一位可以填 0 - (digit[i]-1)若这一位之前挨着49,那么加上 dp[i-1][0] * digit[i] 也是显然对的。若这一位之前没有挨着49,但是digit[i]比4大,那么当这一位填4的时候,就得加上dp[i-1][1]
#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
long long dp[20][3];
int digit[20];
int main()
{
memset(dp,0,sizeof(dp));
dp[0][0] = 1;
for(int i=1; i<20; i++)
{
dp[i][0] = dp[i-1][0] * 10 - dp[i-1][1]; // not include 49
dp[i][1] = dp[i-1][0]; // not include 49 but starts with 9
dp[i][2] = dp[i-1][2] * 10 + dp[i-1][1]; // include 49
}
int t;
cin >> t;
while(t--)
{
int len = 0,last=0;
long long ans = 0;
unsigned long long n=0;
cin >> n;
n++;
memset(digit,0,sizeof(digit));
while(n)
{
digit[++len] = n%10;
n/=10;
}
bool flag = false;
for(int i =len; i>=1; i--)
{
ans += dp[i-1][2] * digit[i];
if(flag)
ans += dp[i-1][0] * digit[i];
if(!flag && digit[i] >4)
ans += dp[i-1][1];
if(last == 4 && digit[i] == 9)
flag = true;
last = digit[i];
}
cout << ans << endl;
}
return 0;
}