らての精進日記

修行をします

aoj2383:Rabbit Game Playing

解法

まずDを昇順にソートする。
Dの先頭からi個(0<=i< N)とって、それらについての通り数をF[i]とする。

条件を満たすあるD[1],...,D[i]の並び替えをとってくる。
この数列にD[i+1]を追加することを考えると、挿入する位置はi+1箇所ある。
このとき、挿入した位置の前後の数字との大小関係が問題になる。
ただ、Dを昇順にソートしているから、挿入位置の前の数字はどうでもよくなって、後ろの数字が重要になる。
後ろにあるやつの数字をdとすれば、d+T>=D[i+1]であればよい。
よって、j<=iかつD[j]+T>=D[i+1]となるjの数とt[i]とすれば、t[i]箇所に挿入できる。
また、末尾には確実に挿入できるので、全体でt[i]+1箇所に挿入できることになる。
D[1],...,D[i]の並び方に関係なくt[i]+1箇所に挿入できるので、F[i+1]=F[i]*(t[i]+1)という漸化式が成り立つ。
また、各iについて、t[i]は尺取り法で計算できる。

よってO(N)

コード

#include<bits/stdc++.h>
using namespace std;

#define int long long
typedef vector<int>vint;
typedef pair<int,int>pint;
typedef vector<pint>vpint;
#define rep(i,n) for(int i=0;i<(n);i++)
#define reps(i,f,n) for(int i=(f);i<(n);i++)
#define all(v) (v).begin(),(v).end()
#define each(it,v) for(__typeof((v).begin()) it=(v).begin();it!=(v).end();it++)
#define pb push_back
#define fi first
#define se second
template<typename A,typename B>inline void chmin(A &a,B b){if(a>b)a=b;}
template<typename A,typename B>inline void chmax(A &a,B b){if(a<b)a=b;}

const int mod=1000000007;

int N,T;
int D[100000];
int dp[100010];

signed main(){
    scanf("%lld%lld",&N,&T);
    rep(i,N)scanf("%lld",&D[i]);
    sort(D,D+N);
    dp[0]=1;
    int l=0;
    rep(i,N){
        while(D[l]+T<D[i])l++;
        dp[i+1]=dp[i]*(i-l+1)%mod;
    }
    printf("%lld\n",dp[N]);

    return 0;
}