JZOJ100045. 【NOIP2017提高A组模拟7.13】好数

来源:互联网 发布:阿里云汽车荣威rx5 编辑:程序博客网 时间:2024/06/15 19:42

Description

我们定义一个非负整数是“好数”,当且仅当它符合以下条件之一:
1.这个数是0或1
2.所有小于这个数且与它互质的正整数可以排成一个等差数列例如,8就是一个好数,因为1,3,5,7排成了等差数列。
给出N个非负整数,然后进行如下三个操作:
1.询问区间[L,R]有多少个好数
2.将区间[L,R]内所有数对S取余(S≤1000000)
3.将第C个数更改为X

分析

首先我们应该找出什么数是好数,
通过打表就可以发现,所以的质数,2的次幂,以及6。

对于操作1和操作3,我们都可以用线段树轻松地维护。
关键是操作2。

如果一个区间的最大值都小于取模的数的话,很显然这次取模是没有意义的,可以不做处理。
可以证明一个数最多会被有效取模log次,
那么时间复杂度就可以保证了。

code

#include <cstdio>#include <algorithm>#include <cstring>#include <string.h>#include <cmath>#include <math.h>#define N 1000003using namespace std;int n,m,a[N],tr[N*4],mx[N*4],ss[N];int x,y,z;bool bz[N*10];char ch;void read(int &n){    n=0;    ch=getchar();    while((ch<'0' || ch>'9') && ch!='-')ch=getchar();    int w=1;    if(ch=='-')w=-1,ch=getchar();    while('0'<=ch && ch<='9')n=n*10+ch-'0',ch=getchar();    n*=w;}void make(int x,int l,int r){    if(l==r)    {        tr[x]=bz[a[l]];        mx[x]=a[l];        return;    }    int m=(l+r)/2;    make(x+x,l,m);    make(x+x+1,m+1,r);    tr[x]=tr[x+x]+tr[x+x+1];    mx[x]=max(mx[x+x],mx[x+x+1]);}int find(int x,int l,int r,int ll,int rr){    if(ll==l && rr==r)return tr[x];    int m=(l+r)/2;    if(rr<=m)return find(x+x,l,m,ll,rr);else        if(ll>m)return find(x+x+1,m+1,r,ll,rr);else            return find(x+x,l,m,ll,m)+find(x+x+1,m+1,r,m+1,rr);}void work(int x,int l,int r,int z){    if(mx[x]<z)return;    if(l==r)    {        mx[x]=mx[x]%z;        tr[x]=bz[mx[x]];        return;    }    int m=(l+r)/2;    work(x+x,l,m,z);    work(x+x+1,m+1,r,z);    tr[x]=tr[x+x]+tr[x+x+1];    mx[x]=max(mx[x+x],mx[x+x+1]);}void change(int x,int l,int r,int ll,int rr,int z){    if(mx[x]<z)return;    if(ll==l && rr==r)    {        work(x,l,r,z);        return;    }    int m=(l+r)/2;    if(rr<=m)change(x+x,l,m,ll,rr,z);else        if(ll>m)change(x+x+1,m+1,r,ll,rr,z);else            change(x+x,l,m,ll,m,z),change(x+x+1,m+1,r,m+1,rr,z);    tr[x]=tr[x+x]+tr[x+x+1];    mx[x]=max(mx[x+x],mx[x+x+1]);}void chan(int x,int y,int l,int r){    if(l==r)    {        mx[x]=z;        tr[x]=bz[mx[x]];        return;    }    int m=(l+r)/2;    if(y<=m)chan(x+x,y,l,m);        else chan(x+x+1,y,m+1,r);    tr[x]=tr[x+x]+tr[x+x+1];    mx[x]=max(mx[x+x],mx[x+x+1]);}void write(int x){     if(x>9) write(x/10);     putchar(x%10+'0');}int main(){    memset(bz,1,sizeof(bz));    for(int i=2;i<=1000000;i++)    {        if(bz[i])            ss[++ss[0]]=i;        for(int j=1;j<=ss[0];j++)        {            if(ss[j]*i>1000000)break;            bz[ss[j]*i]=0;            if(i%ss[j]==0)break;        }    }    for(int i=2;i<=1000000;i=i*2)        bz[i]=1;    bz[6]=1;    freopen("good8.in","r",stdin);    freopen("good.out","w",stdout);    read(n);read(m);    for(int i=1;i<=n;i++)        read(a[i]);    make(1,1,n);    for(int k=1;k<=m;k++)    {        read(x);        read(y);        read(z);        if(x==1)write(find(1,1,n,y,z)),printf("\n");else        if(x==2)read(x),change(1,1,n,y,z,x);else            chan(1,y,1,n);    }}
原创粉丝点击