FZU 2109 Mountain Number
http://acm.fzu.edu.cn/problem.php?pid=2109
题意:找出区间[l,r]内满足奇数位的数字大于相邻偶数位数字的个数。
典型的数位dp了,记录一下当前位是奇数位还是偶数位。
状态设计为到当前位为(奇数还是偶数的条件下上一位数字为x的)满足条件的 个数。
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int MAX = 20;
int dp[MAX][MAX][2];
int digit[MAX];
int dfs(int pos,int pre,bool c,bool limit,bool check)
{
if(!pos)
{
if(!check) return 1;
else return 0;
}
if(check) return 0;
if(!limit&&~dp[pos][pre][c]&&!check) return dp[pos][pre][c];
int end=limit?digit[pos]:9; int ans=0;
for(int i=0;i<=end;i++)
{
if(c&&pre<=i) ans+=dfs(pos-1,i,c^1,limit&&(end==i),check);
else if(!c&&pre>=i) ans+=dfs(pos-1,i,c^1,limit&&(end==i),check);
else ans+=dfs(pos-1,i,c^1,limit&&(end==i),check||1);
}
if(!limit&&!check) dp[pos][pre][c]=ans;
return ans;
}
int solve(int n)
{
int cur=0;
while(n)
{
digit[++cur]=n%10;
n/=10;
}
return dfs(cur,9,false,true,false);
}
int main()
{
int cas,L,R;
scanf("%d",&cas);
memset(dp,-1,sizeof(dp));
while(cas--)
{
scanf("%d %d",&L,&R);
printf("%d\n",solve(R)-solve(L-1));
}
}
#include<cstring>
#include<algorithm>
using namespace std;
const int MAX = 20;
int dp[MAX][MAX][2];
int digit[MAX];
int dfs(int pos,int pre,bool c,bool limit,bool check)
{
if(!pos)
{
if(!check) return 1;
else return 0;
}
if(check) return 0;
if(!limit&&~dp[pos][pre][c]&&!check) return dp[pos][pre][c];
int end=limit?digit[pos]:9; int ans=0;
for(int i=0;i<=end;i++)
{
if(c&&pre<=i) ans+=dfs(pos-1,i,c^1,limit&&(end==i),check);
else if(!c&&pre>=i) ans+=dfs(pos-1,i,c^1,limit&&(end==i),check);
else ans+=dfs(pos-1,i,c^1,limit&&(end==i),check||1);
}
if(!limit&&!check) dp[pos][pre][c]=ans;
return ans;
}
int solve(int n)
{
int cur=0;
while(n)
{
digit[++cur]=n%10;
n/=10;
}
return dfs(cur,9,false,true,false);
}
int main()
{
int cas,L,R;
scanf("%d",&cas);
memset(dp,-1,sizeof(dp));
while(cas--)
{
scanf("%d %d",&L,&R);
printf("%d\n",solve(R)-solve(L-1));
}
}