Gym - 102439H(数位DP)

Fibonacci numbers — well-known integer sequence, where F0=0, F1=1 and Fn=Fn−1+Fn−2 for n>1.

Lesha doesn’t like this sequence and all the numbers x, such that we can get positive Fibonacci number by crossing out several digits. For example, Lesha doesn’t like number 193, because it is possible to cross 9 out and get F6=13.

Your task is to find the number of integers from 0 to n which Lesha likes.

Input
The first line contains a single integer t — the number of test cases.

Each of the following t lines contains a single integer n — number, until which you have to count numbers which Lesha likes.

1≤t≤10
0≤n≤1018
Output
Print t lines, each of them should contain a single integer — the answer for the test case.

Example
input

2
4
2019

output

2
125

Note
In the first test suitable numbers are 0 and 4.

题目大意:Lesha不喜欢Fibonacci数列,而且如果这个数删除任意个数字之后是一个斐波拉契数列的话,Lesha也不喜欢这个数字,问在0到n中有多少个数是Lesha喜欢的数。

解题思路:数位DP,先预处理出范围内的Fibonacci数有哪些,然后用map储存一下,然后我们在递归时使用一个rm存储可能是Fibonacci数的一部分的值,然后再pos==0时,在判断这个数是不是Fibonacci数就行啦,但是还有判断一下加入的某一位数是否为Fibonacci数,因为就算只有一位数是Fibonacci数那么也不会取这个数,(虽然其实只需要后面的判断就行了,也就是判断数中有没有1,2,3,5,8这些数)。
代码:

#include <algorithm>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <map>
#include <cmath>
using namespace std;
#define int long long
const int maxn=10000;
int n,k,mod;
int a[maxn],len;
const int inf=(1ll*1)<<61;
map<int,int> mp;
int dp[20][20],f[100],cnt=0;
int dfs(int pos,int sta,int limit,int rm)
{
    if(!pos)return mp.count(rm)==0;
    if(!limit && dp[pos][sta]!=-1){
        return dp[pos][sta];
    }
    if(mp.count(rm))return 0;
    int up=limit?a[pos]:9,ans=0;
    for(int i=0;i<=up;i++){
        int nextrm=rm*10+i;
        int flag=1;
        if(mp.count(i))continue;
        for(int k=1;k<=cnt;k++){
            int l=f[k];
            while(l){
                if(nextrm==l){//如果rm是斐波拉契数列的某个数的其中一部分
                    flag=0;
                    break;
                }
                l/=10;
            }
            if(!flag)break;
            if(f[k]>n)break;
        }
        //cout<
        if(!flag){
            ans+=dfs(pos-1,i,limit&&i==up,nextrm);
        }
        else{
            ans+=dfs(pos-1,i,limit&&i==up,rm);
        }
    }
    if(!limit){
        dp[pos][sta]=ans;
    }
    return ans;
}
int solve(int x)
{
    len=0;
    memset(a,0,sizeof a);
    while(x){
        a[++len]=x%10;
        x/=10;
    }
    return dfs(len,0,1,0);
}
signed main()
{
    f[1]=1;cnt=1;mp[1]=1;
    memset(dp,-1,sizeof dp);
    for(int i=2;i<=89;i++){
        f[++cnt]=f[i-1]+f[i-2];
        mp[f[cnt]]=1;
    }
    //cout<
    int t;
    scanf("%lld",&t);
    while(t--){
        scanf("%lld",&n);
        printf("%lld\n",solve(n));
    }
}

你可能感兴趣的:(数位DP,动态规划)