列表

详情


NC219776. 男神zyh的青睐

描述

这一天,学霸大帅哥zyh带着m个迷妹出门游玩,他们来到一个游乐园,这里有一个游戏是测试俩人的幸运度的。
在他们面前排列着n个糖果,下标从1开始,每个糖果都有一个颜色ai。
游戏的内容是这样的:在每一轮游戏中,zyh会选择下标从l1到r1区间中的糖果中的一个,迷妹会选择l2到r2区间中的糖果中的一个。
(注,zyh选过的糖果迷妹是可以再选的)
我们认为一个迷妹是幸运的,当且仅当抽到的糖果颜色与zyh的相同,求每个迷妹辛运的概率,对1e9+7取模。
对1e9+7取模的含义是:对于一个b不为0的不可约分数,存在q使得b*q mod (1e9+7) = a,q即a/b对1e9+7取模的结果。

输入描述

第一行为俩个整数n和m(1 <= n,m<= 5e4)。代表n个糖果和m个迷妹。
第二行输入n个糖果的颜色ai(1 <= ai <= 5e4)。
接下来m行,每行有四个整数l1,r1,l2,r2代表zyh选择的区间和迷妹选择的区间(l1<=r1,l2<=r2,1<=l1,r1,l2,r2<=n)。

输出描述

共m行。每一行代表该迷妹幸运的概率,结果对1e9+7取模。

示例1

输入:

5 3
1 2 2 3 3
1 4 1 5
2 3 4 5
2 3 2 2

输出:

950000007
0
1

说明:

第一个迷妹,一共会有20种情况,其中有7种会选到一样的颜色,所以概率是7/20=0.35,在模1e9+7的情况下为950000007。
第二个迷妹,无论怎么样都只能选到颜色3的糖果,而zyh只会选到颜色2的糖果,所以幸运概率为0。
第三个迷妹,俩人均只会抽到颜色2的糖果,所以概率是1。

示例2

输入:

3 3
1 1 2
1 2 2 3
1 3 1 3
1 2 1 3

输出:

500000004
555555560
666666672

说明:



原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++(clang++ 11.0.1) 解法, 执行用时: 208ms, 内存消耗: 5196K, 提交时间: 2023-05-24 23:51:47

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

const int maxn=5e4+5;
const int mod=1e9+7;
int a[maxn],cnt[2][maxn],belo[maxn];
struct query{
    int l,r,f,id;
    bool operator <(const query& q)const {
        return belo[l]!=belo[q.l]?(belo[l]<belo[q.l]):((belo[l]&1)?r<q.r:r>q.r);
    }
}q[maxn<<2];
ll now;
int ans[maxn],d[maxn];
inline void add(int &x,int i){
    (now+=cnt[i^1][x])%=mod;
    ++cnt[i][x];
}
inline void del(int &x,int i){
    (now-=cnt[i^1][x])%=mod;
    --cnt[i][x];
}
inline ll qpow(ll x,ll n){
    ll ans=1;
    while(n>0){
        if(n&1)
            ans=ans*x%mod;
        x=x*x%mod,n>>=1;
    }
    return ans;
}

int main() {
    int n,m;scanf("%d%d",&n,&m);
    int blo=pow(n,0.5);
    for(int i=1;i<=n;++i){
        scanf("%d",a+i);
        belo[i]=(i-1)/blo-1;
    }
    for(int i=1;i<=m;++i){
        int l1,r1,l2,r2;scanf("%d%d%d%d",&l1,&r1,&l2,&r2);
        q[4*i-3]={r1,r2,1,i};
        q[4*i-2]={r1,l2-1,-1,i};
        q[4*i-1]={l1-1,r2,-1,i};
        q[4*i]={l1-1,l2-1,1,i};
        d[i]=1ll*(r2-l2+1)*(r1-l1+1)%mod;
    }
    sort(q+1,q+4*m+1);
    int l=0,r=0;
    for(int i=1;i<=4*m;++i){
        int ql=q[i].l,qr=q[i].r,qf=q[i].f;
        while(l<ql) add(a[++l],0);
        while(l>ql) del(a[l--],0);
        while(r<qr) add(a[++r],1);
        while(r>qr) del(a[r--],1);

        (ans[q[i].id]+=now*qf)%=mod;
    }
    for(int i=1;i<=m;++i)
        printf("%lld\n",1ll*(ans[i]+mod)%mod*qpow(d[i],mod-2)%mod);
    return 0;
}

上一题