ZOJ 3940 Modulo Query

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\n",ans%mod);
    }
    return 0;
}

 

posted @ 2016-04-24 13:17  Fighting_Heart  阅读(636)  评论(0编辑  收藏  举报