基础数位dp 跟那个4 62差不多 这个能更简单点 慢慢来吧= 。= 预处理好49连续的情况即可
ps:补一发记忆化的。。用推的15ms 记忆化109…有毒TOT
代码如下:
#include <iostream>
#include <cstdio>
#include <cstring>
#define ll long long
#define sc "%I64d"
using namespace std;
ll dp[20][3];
/*
dp[0] 无连续49
dp[1] 无连续49高位为9
dp[2] 有连续49
*/
void Init()
{
memset(dp,0,sizeof(dp));
dp[0][0] = 1;
int i;
for(i = 1; i <= 19; ++i)
{
dp[i][0] = dp[i-1][0]*10 - dp[i-1][1];
dp[i][1] = dp[i-1][0];
dp[i][2] = dp[i-1][2]*10 + dp[i-1][1];
}
}
ll Solve(ll n)
{
int len = 0,bit[21],i,f = false;
ll ans = 0;
while(n)
{
bit[++len] = n%10;
n /= 10;
}
bit[len+1] = 0;
for(i = len; i; --i)
{
ans += dp[i-1][2]*bit[i];
if(f) ans += dp[i-1][0]*bit[i];
if(!f && bit[i] > 4) ans += dp[i-1][1];
if(bit[i+1] == 4 && bit[i] == 9) f = true;
}
return ans;
}
int main()
{
int t;
ll n;
scanf("%d",&t);
Init();
while(t--)
{
scanf(sc,&n);
printf(sc,Solve(n+1));
puts("");
}
return 0;
}
#include <iostream>
#include <cstdio>
#include <cstring>
#define ll long long
using namespace std;
ll dp[20][3];
int digit[20];
/*
hav =
0 没有连续49
1 没有连续49前位为4
2 有连续49
high 高位是否出现 未出现则随意填
*/
ll dfs(int pos,int hav,bool high)
{
if(pos == -1) return hav == 2;
if(!high && ~dp[pos][hav]) return dp[pos][hav];
int i,nhav,en;
ll ans = 0;
en = high? digit[pos]: 9;
for(i = 0; i <= en; ++i)
{
nhav = hav;
if(!nhav && i == 4) nhav = 1;
else if(nhav == 1 && i == 9) nhav = 2;
else if(nhav == 1 && i != 4) nhav = 0;
ans += dfs(pos-1,nhav,high && i == en);
}
if(!high) dp[pos][hav] = ans;
return ans;
}
ll Solve(char *x)
{
memset(dp,-1,sizeof(dp));
int len = strlen(x);
int i;
for(i = 0; i < len; ++i)
digit[i] = x[len-i-1]-'0';
return dfs(len-1,0,1);
}
int main()
{
int t;
char n[21];
scanf("%d",&t);
while(t--)
{
scanf("%s",n);
printf("%I64d\n",Solve(n));
}
return 0;
}