ZOJ 3940 Modulo Query

由题意可知 F ( n , x ) = ( ( x % A 1 ) % A 2 ) ⋯ % A n F(n,x) = ((x \% A_1) \% A_2) \cdots \%A_n F(n,x)=((x%A1)%A2)%An
现给出Q个询问,求 F ( n , x ) = y F(n,x) = y F(n,x)=y的解的个数, x &lt; = m x &lt;= m x<=m

对于一个区间 [ 0 , x ) [0, x) [0,x), 和数m, 若 x &lt; m , &ThickSpace; [ 0 , x ) % m ∈ [ 0 , x ) x &lt; m, \; [0, x) \% m \in [0, x) x<m,[0,x)%m[0,x)
x &gt; m , &ThickSpace; [ 0 , x ) % m x &gt; m, \; [0, x) \% m x>m,[0,x)%m将得到 [ x / m ] [x / m] [x/m] [ 0 , m ) [0, m) [0,m)区间和1个 [ 0 , x % m ) [0, x \% m) [0,x%m)区间
对于每一个 m m m, 就把所有 &gt; m &gt;m >m的区间都做处理

AC代码:

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

typedef long long ll;

const int mod = 1e9+7;

map <int, int> mp;
vector < pair<int, int> > pr;

int main()
{
    int T, n, m;
    cin >> T;
    while (T--) {
        mp.clear();
        pr.clear();
        scanf("%d %d", &n, &m);
        mp[m+1] = 1;
        int x, q, cnt = 0;
        for (int i = 0; i < n; ++i) {
            scanf("%d", &x);
            //cout << "test: " << x << " "    <<mp.rbegin() -> first << '\n';
            while (mp.rbegin() -> first > x) {
                auto v = *mp.rbegin();
                mp.erase(v.first);
                mp[x] += v.second * (v.first / x);
                if (v.first % x)    mp[v.first % x] += v.second;
            }
        }
        auto v = mp.begin();
        ll ans = 0;
        scanf("%d", &q);
        for (int i = 1; i <= q; ++i) {
            scanf("%d", &x);
            pr.push_back(make_pair(x, i));
        }
        sort(pr.rbegin(), pr.rend());
        auto its = mp.rbegin();
        for (auto it = pr.begin(); it != pr.end(); ++it) {
            while (its != mp.rend() && its -> first > it -> first) {
                cnt += its -> second;
                its++;
                //cout << "tes: " << its -> first << '\n';
            }
            (ans += (ll) it -> second * cnt) %= mod;
        }
        cout << ans << '\n';
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值