推奨デジタル+ DPエントリの詳細なトピック

未完、明日更新


我々が開始する前に、の質問を見てみましょう- トピックリンク

被験者の要件、隣り合う2以上の差が、我々は最初の試みを構築します。

例えば、\(15246 \)この数、のために最初のものをみましょう(1 \)を\、および第2のビットが\(5 \)、\は(5-1 = 4> 2 \)ように修飾された、第三のビットが\(2 \)、\ (5-2 = 3> 2 \)の条件を満たし、第4ビットである(4 \)を\ \ (= 2 \ 4-2)の条件を満たし、5番目のビットである(\します6 \)、\ (6-4 = 4 \)修飾ので、予選の数。

私たちは番号の数を構築するのであれば問題は、複雑さは明らかに問題であるが、我々は、最適化する必要があります。ビュー\(15246 \)\(96246 \)これら二つの数字、彼らはルールに沿ったものであるが、それら3が同じになった後、我々は簡単限りで下から4のように、と考えることができます(\ 2 \)ルールと貧しい遵守、限り3のように)\(246 \それがルールに沿ったものでなければならない、それは私たちが裁判官を繰り返す必要はありませんと言うことです。

身近なものの一切考えはありませんか?はい、のメモリ!いくつかの処理された後、私たちは、直接使用することができたときに、設定をバックアップするフロントではなく、時間を節約し、再決定します。

単に列挙の下で、非常にシンプルである現在位置との差を見て、ルールを満たしていると判断されます。また、要求されたトピックは除いて、つまり、先行ゼロが含まれていません\(0 \)を使用することが許可されていない自分自身以外の任意の数の\(0 \)が最初で、その後、最初の初めから、我々は一流の記録\(0 \)がある場合ない\(0 \)その後、状況は特に制限はなく、最初の非ゼロ先行ゼロのビットの後に、先行ゼロなしで記録されています。

その後、我々はプログラムそれを見て

#include<iostream>
#include<cstring>
#include<cstdio>
#include<cctype>
#include<cmath>
#define ll long long
#define gc() getchar()
#define maxn 15
using namespace std;

inline ll read(){
    ll a=0;int f=0;char p=gc();
    while(!isdigit(p)){f|=p=='-';p=gc();}
    while(isdigit(p)){a=(a<<3)+(a<<1)+(p^48);p=gc();}
    return f?-a:a;
}
void write(ll a){
    if(a>9)write(a/10);
    putchar(a%10+'0');
}

int x,y,d[maxn],l;
ll f[maxn][maxn];
ll dfs(int pos,int pre,bool limit,bool lead){  //pos表示从后往前数第pos位,pre记录前一位我们选择的数值,limit记录当前是不是卡着最大值,如果卡着最大值就不能从[0,9]中任意选数,而是在[0,区间右端点当前位的数值]之间选数,lead就是记录前导零的问题了
    if(!pos)return 1;  //如果所有位都已经构造完了,说明这是一个合法数值,贡献加一
    if(!limit&&!lead&&~f[pos][pre])return f[pos][pre];  //如果已经处理过特殊要求均相同的情况,直接返回答案,避免重复计算
    int up=limit?d[pos]:9;ll ans=0;  //up就是当前位选数的右端点
    for(int i=0;i<=up;++i){  //枚举构造
        if(abs(i-pre)<2&&!lead)continue;  //如果不合法则跳过
        ans+=dfs(pos-1,i,limit&&i==d[pos],lead&&!i);
    }
    if(!limit&&!lead)f[pos][pre]=ans;  //这里有多种写法,其实就是要求你把各种特殊状态都记录下来
    return ans;
}

ll solve(int k){
    l=0;
    while(k){  //这里是为了记录一下当前范围最大是几位
        d[++l]=k%10;
        k/=10;
    }
    return dfs(l,0,1,1);
}

int main(){memset(f,-1,sizeof f);
    x=read();y=read();
    write(solve(y)-solve(x-1));  //答案要求是[x,y]之间的windy数,所以减去[0,x)的windy数即可
    return 0;
}

おすすめ

転載: www.cnblogs.com/hanruyun/p/11454535.html