题意:给你一个区间[1,r],然后在这个区间中的数字,从左往右看如果是先递增再递减的,这个就是山峰数,求这个区间中不是山峰数的数量。。
分析:开始题目看错了,原来一个数字中只用出现一段是先增后减的,就算山峰。。比如12100-12199都是山峰数
#include <iostream>
#include <cmath>
#include <algorithm>
#include <cstdio>
#include <cstring>
using namespace std;
int s[105];
#define ll long long
#define inf 1000000007
char n[105];
ll dp[105][5][20];//题目理解的有问题,如果有的话,就全算
ll swdp(int pos,int lead,int ud,int now,int limit,int num)//当前位置,有无前导0,,现在是上升还是下降还是符合条件的,有无限制,现在是第几个数字(无前导零)
{
if(pos<=0) return ud==3;
if(!limit&&dp[pos][ud][now]!=-1) return dp[pos][ud][now];
int ed = limit?s[pos]:9;
ll ret=0;
for(int i=0;i<=ed;i++)
{
int t1=ud;
if(!lead&&num>=1&&t1<3){
if(i<now)//递减
{
if(t1==0)
t1=1;
else if(t1==2)
t1=3;
}
else if(i>now)//递增
t1=2;
}
ret=(ret+swdp(pos-1,lead&&i==0,t1,i,limit&&i==ed,num+(lead&&i==0?0:1)))%inf;
}
if(!limit) dp[pos][ud][now]=ret%inf;
return ret%inf;
}
ll zz=0;
ll solve(ll b)
{
memset(s,0,sizeof(s));
int u=0;
while(b>0)
{
s[++u]=n[--b]-'0';
}
for(int i=u;i>=1;i--)
{
zz=(zz*10%inf+s[i])%inf;
}
ll ans=swdp(u,1,0,0,1,0)%inf;
return ans;
}
int main()
{
int T;
scanf("%d",&T);
memset(dp,-1,sizeof(dp));
while(T--)
{
scanf("%s",n);
int len=strlen(n);
zz=0;
ll k=solve(len);
ll zzz=(zz-k+inf)%inf;//不用k,直接用solve(len)来表示,用G++提交会wa?!
printf("%I64d\n",zzz);
}
return 0;
}