Coprimes Gym - 101492C(bitset)

思路:处理每一位右边第一组互质的数的右边数的位置,O(1)处理查询;

 

我们先处理对于一个数右边第一个与它互质的数

从n->1开始

对于每一个数 对其进行素因数分解,记录每一个素数被那些数所包含

同时二进制标记处理其本身与那些数不互质

最后对i-n取反 找第一个1出现的位置,就是右边与它互质的第一个数的位置

 

这样我们处理完了右边第一个和它互质数的位置,

对于第i个数 右边第一对互质的数的右边数的位置应是 min(ans[i],ans[i+1],....ans[n]);

如果n->1跑的的 就可以写成min(ans[i],ans[i+1]) ps:处理i时i+1已经处理结束;

这样就可以O(1)处理答案了

#include<bits/stdc++.h>
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<queue>
#include<set>
#include<map>
#include<vector>
#include<bitset>

#define inf 0x3f3f3f3f
#define mem(a,b) memset(a,b,sizeof(a))
#define ll long long
#define sd(x) scanf("%d",&(x))
#define sl(x) scanf("%lld",&(x))
#define slf(x) scanf("%lf",&(x))
#define scs(s) scanf("%s",s)
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define per(i,a,b) for(int i=a;i>=b;i--)
#define lowbit(x) x&(-x)
#define ls now<<1
#define rs now<<1|1
#define lson l,mid,ls
#define rson mid+1,r,rs
#define All L,R
using namespace std;

const int maxn=5e4+10;

int is_prime[maxn*10],prime[maxn],ans[maxn],a[maxn],tot=0,has[maxn*10];

bitset<maxn> dp[maxn],mark,ok;


void make()
{
    is_prime[1]=is_prime[0]=true;
    for(int i=2;i<=5e5;i++)
    {
        if(!is_prime[i])
        {
            prime[++tot]=i;
        }
        for(int j=1;j<=tot&&i*prime[j]<=5e5;j++)
        {
            is_prime[i*prime[j]]=true;
            if(i%prime[j]==0)
            {
                break;
            }
        }
    }
}

int main()
{
    int n,m;
    make();
    for(int i=0;i<tot;i++)
        has[prime[i+1]]=i;
    cin>>n>>m;
    rep(i,1,n) cin>>a[i];
    ans[n+1]=maxn;
    for(int i=n;i>=1;i--)
    {
        mark.reset();
        mark[i]=1;
        ok[i]=1;
        for(int j=1;prime[j]*prime[j]<=a[i];j++)
        {
            if(a[i]%prime[j]==0&&a[i])
            {
                dp[has[prime[j]]][i]=1;
                mark|=dp[has[prime[j]]];
            }
            while(a[i]%prime[j]==0&&a[i])
            {
                a[i]/=prime[j];
            }
        }
        if(a[i]) dp[has[a[i]]][i]=1,mark|=dp[has[a[i]]];
        ans[i]=(mark^ok)._Find_first();
        ans[i]=min(ans[i],ans[i+1]);
    }
    while(m--)
    {
        int l,r;
        cin>>l>>r;
        if(ans[l]<=r) cout<<"S\n";
        else cout<<"N\n";
    }


    return 0;
}

 

posted @ 2019-08-21 11:01  Minun  阅读(223)  评论(0编辑  收藏  举报