百度之星2017复赛1005 HDU-6148 Valley Numer
题意
不出现上升后直接下降数位的数,不超过n的有几个。前导零不算。
题解
dfs(当前数位的位置len,这位的数num,是否在上升up,是否有限制limit) limit不用存到状态里,因为limit为true时不可能访问两次。 num=-1代表还没开始这个数的第一位,前面是前导零。 up=1时,不允许下降。
代码
代码语言:javascript复制#include <bits/stdc .h>
#define mem(a,b) memset(a,b,sizeof(a))
#define ll long long
#define N 105
const ll M = 1e9 7;
using namespace std;
int t;
char s[N];
int mlen;
ll st[N][11][2];
void add(ll &x,ll v){
x =v;if(x>=M)x-=M;
}
ll dfs(int len,int num,int up,bool limit);
void work(int len,int num,int up,bool limit,int i,ll &ans){
if(num==-1 && i==0){
add(ans,dfs(len 1,-1,0,limit));
}else{
if(num==-1){
add(ans,dfs(len 1,i,0,limit));
}else if(i<num){
if(up==0)
add(ans,dfs(len 1,i,0,limit));
}else if(i==num){
add(ans,dfs(len 1,i,up,limit));
}else{
add(ans,dfs(len 1,i,1,limit));
}
}
}
ll dfs(int len,int num,int up,bool limit){
if(len==mlen) return num != -1;
if(!limit && (~num)&&(~st[len][num][up]))return st[len][num][up];
ll ans=0;
int b=limit?s[len]-'0':9;
for(int i=0;i<=b; i)
work(len,num,up,i==b&&limit,i,ans);
return num<0||limit?ans:st[len][num][up]=ans;
}
int main(){
scanf("%d",&t);
while(t--){
scanf("%s",s);
mlen=strlen(s);
mem(st,-1);
printf("%lldn",dfs(0,-1,0,1));
}
return 0;
}