设f[i] 为至少击败 i个怪兽的方案数 那么
击败i个的方案数则为 f[i] - f[i + 1]
答案即为 1~n f[i]的求和
设sum[i]为前 i个怪兽的攻击力
因为能量从1 ~ n分别为 0~n - 1那么 1 ~ i + 1都是可以被选择为前 i 个的 所以每次就是 乘2
如果sum[i] >= m的话那么就是 2^i * fac[n - i]
如果sum[i] < m的话 就要从前面选择一个 去减掉 因为每次都乘 fac[n - i]所以和只需要看 i 只需要存一个优先队列 判断即可
#include<iostream>
#include<cstring>
#include<queue>
#define x first
#define y second
using namespace std;
const int N = 5e5 + 10,mod = 1e9 + 7;
typedef pair<int,int> PII;
typedef long long ll;
ll a[N];ll b[N],f[N];
ll fac[N];
priority_queue<PII,vector<PII>,greater<PII> > q;
ll qpow(ll a,ll b){
if(b == -1) return 1;
ll s = 1;
while(b){
if(b & 1) s = s * a % mod;
a = a * a % mod;
b >>= 1;
}
return s;
}
int main(){
fac[0] = 1;
for(int i = 1; i <= 5e5; i++){
fac[i] = 1ll * fac[i - 1] * i % mod;
}
ll n,m;
cin >> n >> m;
for(int i = 1; i <= n; i++){
scanf("%lld",&a[i]);
b[i] = b[i - 1] + a[i];
}
q.push({
a[1],1});
ll ans = 0;
ll sum = 0;
sum += 1;
for(int i = 1; i <= n - 1; i++){
q.push({
a[i + 1],i + 1});
sum += qpow(2,i - 1);
sum %= mod;
if(b[i + 1] <= m){
ans += qpow(2,i) * fac[n - i] % mod;
}else{
while(q.size()){
PII p = q.top();
if(b[i + 1] - p.x <= m) break;
sum -= qpow(2,p.y - 2);
sum %= mod;
sum += mod;
sum %= mod;
q.pop();
}
ans += sum * fac[n - i] % mod;
}
ans %= mod;
}
if(b[n] <= m) ans += qpow(2,n - 1);
cout << ((ans) % mod + mod) % mod << endl;
return 0;
}