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 < = m x <= m x<=m

对于一个区间 [ 0 , x ) [0, x) [0,x), 和数m, 若 x < m ,    [ 0 , x ) % m ∈ [ 0 , x ) x < m, \; [0, x) \% m \in [0, x) x<m,[0,x)%m[0,x)
x > m ,    [ 0 , x ) % m x > 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, 就把所有 > m >m >m的区间都做处理

AC代码:

#include 
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 << " "    < 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;
}

你可能感兴趣的:(题目集)