0--M对某个数字取模,相当于把0--M区间进行切割,每次暴力切割一下。结果的算的时候二分一下即可。。。
看了官方题解才会。。。
#include<cstdio> #include<cstring> #include<queue> using namespace std; const int maxn=100000+10; long long mod=1e9+7; int T,m,sz; struct X { int x; long long y; bool operator<(const X&a)const { return x < a.x; } X(int a,long long b) {x=a,y=b;} }; long long sum[maxn],cnt[maxn]; int v[maxn]; long long get(int now) { long long res=0; int l=0,r=sz-1; while(l<=r) { int mid=(l+r)/2; if(v[mid]>=now) { l=mid+1; res=sum[mid]; } else r=mid-1; } return res; } int main() { scanf("%d",&T); while(T--) { int n; scanf("%d%d",&n,&m); priority_queue<X>q; q.push(X(m,1)); for(int i=1;i<=n;i++) { int x; scanf("%d",&x); while(1) { if(q.top().x<x) break; X head=q.top(); q.pop(); q.push(X(x-1, (head.x + 1) / x*head.y)); if ((head.x+1)%x>=1) q.push(X(head.x%x, head.y)); } } sz=0; v[sz]=q.top().x; cnt[sz]=q.top().y; q.pop(); sz++; while(!q.empty()) { X head=q.top(); q.pop(); if(head.x==v[sz-1]) cnt[sz-1]+=head.y; else { v[sz]=head.x; cnt[sz]=head.y; sz++; } } sum[0]=cnt[0]; for(int i=1;i<sz;i++) sum[i]=sum[i-1]+cnt[i]; int Q; scanf("%d",&Q); long long ans=0; for(long long i=1;i<=Q;i++) { int g; scanf("%d",&g); ans=(ans+i*get(g)%mod)%mod; } printf("%lld ",ans%mod); } return 0; }