一个很暴力的递归拆分过程改成priority_queue就过了,醉了
#include <cstdio> #include <iostream> #include <vector> #include <cstring> #include <queue> #include <cmath> #include <algorithm> using namespace std; typedef long long ll; typedef long long LL; const int mod = 1e9 + 7; const int N = 1e5 + 100; int a[N] , n ,m; int cnt[N],min_; struct San :vector<int>{ void prepare(){ sort(begin(),end()); erase(unique(begin(),end()),end()); } int get_l(int x){ return (int)(lower_bound(begin(),end(),x)-begin())+1; } int get_r(int x){ return (int)(upper_bound(begin(),end(),x)-begin())+1-1; } }id; vector<pair<int,int> > v; int all = 0; struct node{ int x , y; node(){} node(int x , int y):x(x),y(y){} bool operator <(const node& rhs)const{ return x < rhs.x; } }; void cal(int p,int max_ , int num){ priority_queue<node> Q; Q.push(node(m , 1)); for(int i = 1 ; i<=n; i++){ int x = a[i] , cnt = 0; while(Q.top().x >= x){ node u = Q.top(); Q.pop(); Q.push(node(x - 1 , ((u. x + 1)/x) * u.y)); if((u.x + 1)% x) Q.push(node((u.x + 1)% x - 1 , u.y)); } } while(!Q.empty()){ node u = Q.top(); Q.pop(); all += u.y; v.push_back(make_pair(u.x , u.y)); } } int query[N],ans[N]; int main() { int T; scanf("%d",&T); while(T--){ scanf("%d %d",&n,&m); min_= mod + 1; for(int i =1;i<=n;i++) scanf("%d",&a[i]),min_ = min(min_ , a[i]); int Q; scanf("%d",&Q); id.clear(); for(int i =1;i<=Q;i++){ int y; scanf("%d",&query[i]); id.push_back(query[i]); } id.prepare(); v.clear(); all =0; cal(1 , m + 1 , 1); sort(v.begin(),v.end()); int pos = 0; for(int i = 0 ; i<id.size() ; i++){ while(pos < v.size() && v[pos].first < id[i]){ all-=v[pos].second; ++pos; } ans[i + 1] = all; } int Ans =0; for(int i = 1 ; i<=Q; i++){ Ans = (Ans + (ll)i * ans[id.get_l(query[i])] % mod) % mod; } printf("%d\n",Ans); } return 0; }