解题思路
设f_{len,last,k}为填了len位,上一位为last,目前上升(k=1)和下降(k=2)状态为k(0表示未知)
记得判前导0。
代码
#include<iostream>
#include<cstdio>
#include<iomanip>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<queue>
using namespace std;
const unsigned long long mod=1e9+7;
int T;
unsigned long long f[110][15][3],c[110];
string n;
unsigned long long dp(int len,int last,int k,int limit,int zero){
if(!len)
return !zero;
if(!limit&&f[len][last][k]!=-1)return f[len][last][k];
unsigned long long ans=0;
int maxx=(limit?c[len]:9);
for(int i=0;i<=maxx;i++)
{
if(k==1&&i<last)continue;
if(zero)ans=(ans+dp(len-1,i,k,limit&&(i==c[len]),zero&&(i==0)))%mod;
else if(i==last)ans=(ans+dp(len-1,i,k,limit&&(i==c[len]),0))%mod;
else ans=(ans+dp(len-1,i,(i<last?2:1),limit&&(i==c[len]),0))%mod;
}
if(!limit) f[len][last][k]=ans;
return ans;
}
unsigned long long solve(string a)
{
memset(f,-1,sizeof(f));
int pos=0;
for(int i=a.size()-1;i>=0;i--)
c[++pos]=a[i]-'0';
return dp(pos,0,0,1,1);
}
int main(){
scanf("%d",&T);
while(T--)
{
cin>>n;
cout<<solve(n)<<endl;
}
}