818E - Card Game Again 双指针+分解质因数

题意:

有多少种 x y 的选择方法,使得对于长度为 n 的 a 数组, 取  a[x+1] ,a[x+2] ... a[y-2] , a[y-1] 的乘积是 k 的倍数 

思路:

对于所有的 x ,当选择 x = x + 1 时 y = y  满足条件 ,则此时取 x = x ,y = y 也满足条件 。所以可以用双指针

只要 x  到 y 之间的所有数的乘积的 因子的个数 大于等于 k 的所有因子的个数就满足条件, 此时对于所有 y >= y 的情况也都满足条件 

由于 数据是 1e9,所以如果某个因子大于 根号1e9,它就是这个数本身,这个数是个质数, 且在k中最多只会出现一次,所以可以存到一个set里

//#define int ll
const int N = 2e5+10,maxn = 3e4 + 2e3;
int n,k;
int is[maxn];
V<int>prime;
void init() {
    fo(i,2,maxn-1) {
        if(!is[i]) {
            prime.pb(i);
            for(ll j = 1ll * i * i; j < maxn;j += i) {
                is[j] = 1;
            }
        }
    }
}
int a[N];
struct nd {
    int x,cnt;
};
V<nd> getFactor(int x) {
    V<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.pb(nd{prime[i],c});
    }
    if(x > 1) v.pb(nd{x,1});
    return v;
}
map<int,V<nd>> mp;
int C[maxn];
set<int> st;
void solve()
{
    init();
    cin>>n>>k;
    fo(i,0,n-1) {
        cin>>a[i];
    }
    int l = 0,r = 0;
    V<nd> K = getFactor(k);
    ll ans = 0;
    int state = 1;
    while(l < n && r < n) {
        V<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); //如果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) { // 如果 k 的这个因子大小比 maxn 大 
                if(!st.count(K[i].x)) {// 如果st 中不包括这个因子 
                    flg = 1;break;
                }
            } else if(K[i].cnt > C[K[i].x]) { // 如果因子少,flg = 1 
                flg = 1;break;// K是k 中的因子 , 
            }
        }
        if(flg) { // 失败了就往右边找 
            r ++ ;
            state = 1;
        } else {
            ans += n - r;
            if(l == r) {
                l ++ ;r ++ ;state = 1;ms(C,0);st.clear();
            } else state = 0;
        } 
    }
    cout<<ans<<endl;
     rt;
} 

 

posted @ 2022-11-10 23:18  er007  阅读(23)  评论(0编辑  收藏  举报