1. 程式人生 > 其它 >[ HNOI2016 ] 大數

[ HNOI2016 ] 大數

題目

Luogu
LOJ
Acwing

思路


程式碼

#include <iostream>
#include <algorithm>
#include <vector>
#include <cstring>
#include <cmath>
#define int long long
using namespace std;
const int N = 200010;
int n, P, m, f[N], s[N], id[N], res[N];
struct QUERY { int l, r, id; } Q[N];
bool operator<(QUERY a, QUERY b) { 
    if (id[a.l] != id[b.l]) return a.l < b.l;
    return id[a.l] & 1 ? a.r < b.r : a.r > b.r;
}
char str[N];
vector<int> nums;
void init() {
    n = strlen(str + 1);
    int B = sqrt(n), S = (n + B - 1) / B, pow = 1;
    for (int i = n; i >= 1; i--) {
        s[i] = ((str[i] - '0') * pow % P + s[i + 1]) % P;
        nums.push_back(s[i]);
        pow = pow * 10 % P, id[i] = (i + B - 1) / B;
    }
    nums.push_back(0);
    sort(nums.begin(), nums.end());
    nums.erase(unique(nums.begin(), nums.end()), nums.end());
    for (int i = 1; i <= n + 1; i++) 
        s[i] = lower_bound(nums.begin(), nums.end(), s[i]) - nums.begin();
}
int A[N], B[N];
void work1() {
    for (int i = 1; i <= n; i++) {
        A[i] = A[i - 1] + (!((str[i] - '0') % P));
        B[i] = B[i - 1] + (!((str[i] - '0') % P)) * i;
    }
    for (int i = 1, l, r; i <= m && cin >> l >> r; i++)
        cout << (B[r] - B[l - 1] - (A[r] - A[l - 1]) * (l - 1)) << endl;
}
int ans = 0;
void del(int x) { f[x]--, ans -= f[x]; }
void upd(int x) { ans += f[x], f[x]++; }
void work2() {
    for (int i = 1; i <= m; i++) 
        cin >> Q[i].l >> Q[i].r, Q[i].r++, Q[i].id = i;
    sort(Q + 1, Q + m + 1);
    int l = 1, r = 0;
    for (int i = 1; i <= m; i++) {
        while (l < Q[i].l) del(s[l++]);
        while (l > Q[i].l) upd(s[--l]);
        while (r < Q[i].r) upd(s[++r]);
        while (r > Q[i].r) del(s[r--]);
        res[Q[i].id] = ans;
    }
    for (int i = 1; i <= m; i++) cout << res[i] << endl;
}
signed main() {
    cin >> P >> str + 1 >> m;
    init(), (P == 2 || P == 5) ? work1() : work2();
    return 0;
}