818E - Card Game Again(尺取法)

818E - Card Game Again

题意

给出一个数列,选择连续的一段使得这些数字的乘积是 k 的倍数,问合法的方案数。

分析

尺取法。设 num 为连续的数的乘积,只要对于 k 的每个素因子,num 相应的素因子的个数大于等于它。那么不仅这个数,后面乘上任意数都是 k 的倍数。这时候就不用移动 r 指针了,移动 l 指针,即不断的去掉前面的数。
计算时可以用 map 存下素因子及其个数。

code

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1e5 + 5;
const int MAXN = 3e4 + 2e3;
const int INF = 2e9 + 1;
int is[MAXN];
vector<int> prime;
void init() {
    for(int i = 2; i < MAXN; i++) {
        if(!is[i]) {
            prime.push_back(i);
            for(ll j = 1LL * i * i; j < MAXN; j += i) {
                is[j] = 1;
            }
        }
    }
}
int a[N];
struct nd {
    int x, cnt;
};
vector<nd> getFactor(int x) {
    vector<nd> v;
    for(int i = 0; 1LL * prime[i] * prime[i] <= x; i++) {
        int c = 0;
        while(x % prime[i] == 0) {
            x /= prime[i];
            c++;
        }
        if(c) v.push_back(nd{prime[i], c});
    }
    if(x > 1) v.push_back(nd{x, 1});
    return v;
}
map<int, vector<nd> > mp;
int C[MAXN];
set<int> st;
int main() {
    ios::sync_with_stdio(0);
    cin.tie(0);
    init();
    int n, k;
    cin >> n >> k;
    for(int i = 0; i < n; i++) {
        cin >> a[i];
    }
    int l = 0, r = 0;
    vector<nd> K = getFactor(k);
    ll ans = 0;
    int state = 1;
    while(l < n && r < n) {
        vector<nd> X;
        if(state) {
            if(!mp.count(a[r])) mp[a[r]] = getFactor(a[r]);
            X = mp[a[r]];
            for(int i = 0; i < X.size(); i++) {
                if(X[i].x > MAXN) st.insert(X[i].x);
                else C[X[i].x] += X[i].cnt;
            }
        } else {
            if(!mp.count(a[l])) mp[a[l]] = getFactor(a[l]);
            X = mp[a[l]];
            for(int i = 0; i < X.size(); i++) {
                if(X[i].x > MAXN) st.erase(X[i].x);
                else C[X[i].x] -= X[i].cnt;
            }
            l++;
        }
        int flg = 0;
        for(int i = 0; i < K.size(); i++) {
            if(K[i].x > MAXN) { if(!st.count(K[i].x)) { flg = 1; break; } }
            else if(K[i].cnt > C[K[i].x]) { flg = 1; break; }
        }
        if(flg) {
            r++;
            state = 1;
        } else {
            ans += n - r;
            if(l == r) { r++; l++; state = 1; memset(C, 0, sizeof C); st.clear(); }
            else state = 0;
        }
    }
    cout << ans << endl;
    return 0;
}
posted @ 2017-07-11 17:03  ftae  阅读(280)  评论(0编辑  收藏  举报