好数

题目背景

SOURCE:NOIP2016-AHSDFZ T3

题目描述

我们定义一个非负整数是“好数”,当且仅当它符合以下条件之一:

1. 这个数是 0 或 1 。

2. 所有小于这个数且与它互质的正整数可以排成一个等差数列,例如,8 就是一个好数,因为 1,3,5,7 排成了等差数列。

给出 N 个非负整数,然后进行如下三个操作:

1. 询问区间 [L,R] 有多少个好数。

2. 将区间 [L,R] 内所有数对 S 取余(S≤1000000)。

3. 将第 C 个数更改为 X 。

提示:如果你不知道如何判断一个数是否为好数,你可以打个表找找规律。

输入格式

第一行包含两个正整数 N 和 M ,M 表示操作数目。

第二行包含 N 个非负整数。

接下来的 M 行每行表示 1 个操作:“1 L R”表示第 1 个操作,“2 L R S”表示第 2 个操作,“3 C X”表示第 3 个操作。

输出格式

对每个操作1,输出一个非负整数,表示区间内好数的个数。

样例数据 1

输入

3 6

4 6 9

1 1 3

1 3 3

2 1 1 10

1 1 3

3 2 4

1 1 3

输出

2

0

2

2

样例数据 2

输入

8 5

12 24 17 31 16 21 18 30

1 2 5

2 4 7 7

3 2 13

1 1 8

1 3 6

输出

3

6

4

备注

【数据规模与约定】

这里写图片描述
事实上在打表找完规律之后会发现好数只有质数,0,6,和2的非负整数次幂。这样的话,我们可以快速判断一个数是不是好数。然后分析一下算法,每个数每次被取模至少变成原来的0.5倍,于是logn" role="presentation" style="position: relative;">lognlogn次取模之后就成1了,这样的话直接暴力修改,每次单点修改会为时间复杂度提供logn" role="presentation" style="position: relative;">lognlogn的贡献,最多是O(nlogn)" role="presentation" style="position: relative;">O(nlogn)O(nlogn)的贡献,于是将区间取模分解成单点取模,记录区间最大值剪枝就行了。实在不放心的可以线性筛个素数什么的。

代码如下:

#include<bits/stdc++.h>
#define lc (p<<1)
#define rc (p<<1|1)
#define mid (T[p].l+T[p].r>>1)
#define N 100005
using namespace std;
inline long long read(){
    long long ans=0,w=1;
    char ch=getchar();
    while(!isdigit(ch)){
        if(ch=='-')w=-1;
        ch=getchar();
    }
    while(isdigit(ch))ans=(ans<<3)+(ans<<1)+ch-'0',ch=getchar();
    return ans*w;
}
inline int lowbit(int x){return x&-x;}
int n,m,k,a[N];
bool f[105];
inline int prime(int x){
    for(int i=2;i*i<=x;++i)if(x%i==0)return 0;
    return 1;
}
inline int check(int x){
    if(x<=6)return 1;
    if(x==lowbit(x))return 1;
    return prime(x);
}
struct Node{int minn,maxn,lz,l,r,sum,up;}T[N<<2];
inline void pushup(int p){
    T[p].maxn=max(T[lc].maxn,T[rc].maxn);
    T[p].minn=min(T[lc].minn,T[rc].minn);
    T[p].sum=T[lc].sum+T[rc].sum;
}
inline void pushnow(int p,int v,int t){T[p].maxn=T[p].minn=T[p].lz=v,T[p].sum=(T[p].up=t)*(T[p].r-T[p].l+1);}
inline void pushdown(int p){
    if(!T[p].lz)return;
    pushnow(lc,T[p].lz,T[p].up);
    pushnow(rc,T[p].lz,T[p].up);
    T[p].lz=0;
    T[p].up=0;
}
inline void build(int p,int l,int r){
    T[p].l=l,T[p].r=r,T[p].lz=0,T[p].up=0;
    if(l==r){
        T[p].maxn=T[p].minn=a[l];
        T[p].sum=check(a[l]);
        return;
    }
    build(lc,l,mid);
    build(rc,mid+1,r);
    pushup(p);
}
inline void modify(int p,int k,int v){
    if(T[p].l==T[p].r){
        T[p].maxn=T[p].minn=v;
        T[p].sum=check(v);
        return;
    }
    pushdown(p);
    if(k<=mid)modify(lc,k,v);
    else modify(rc,k,v);
    pushup(p);
}
inline void update(int p,int ql,int qr,int v){
    if(qr<T[p].l||T[p].r<ql||T[p].maxn<v)return;
    if(ql<=T[p].l&&T[p].r<=qr&&T[p].maxn==T[p].minn){
        pushnow(p,v,check(v));
        return;
    }
    pushdown(p);
    if(qr<=mid)update(lc,ql,qr,v);
    else if(ql>mid)update(rc,ql,qr,v);
    else update(lc,ql,mid,v),update(rc,mid+1,qr,v);
    pushup(p);
}
inline int query(int p,int ql,int qr){
    if(qr<T[p].l||T[p].r<ql)return 0;
    if(ql<=T[p].l&&T[p].r<=qr)return T[p].sum;
    pushdown(p);
    if(qr<=mid)return query(lc,ql,qr);
    if(ql>mid)return query(rc,ql,qr);
    return query(lc,ql,mid)+query(rc,mid+1,qr);
}
int main(){
    freopen("good.in","r",stdin);
    freopen("good.out","w",stdout);
    n=read(),m=read();
    if(n<=100&&m<=100){
        f[0]=1;
        f[1]=1;
        f[2]=1;
        f[3]=1;
        f[4]=1;
        f[5]=1;
        f[6]=1;
        f[7]=1;
        f[8]=1;
        f[11]=1;
        f[13]=1;
        f[16]=1;
        f[17]=1;
        f[19]=1;
        f[23]=1;
        f[29]=1;
        f[31]=1;
        f[32]=1;
        f[37]=1;
        f[41]=1;
        f[43]=1;
        f[47]=1;
        f[53]=1;
        f[59]=1;
        f[61]=1;
        f[64]=1;
        f[67]=1;
        f[71]=1;
        f[73]=1;
        f[79]=1;
        f[83]=1;
        f[89]=1;
        f[97]=1;
        for(int i=1;i<=n;++i)a[i]=read();
        while(m--){
            int op=read(),l=read(),r=read();
            if(op==1){
                int ans=0;
                for(int i=l;i<=r;++i)ans+=f[a[i]];
                printf("%d\n",ans);
            }
            else if(op==2){
                int s=read();
                for(int i=l;i<=r;++i)a[i]%=s;
            }
            else a[l]=r;
        }
    }
    else{
        build(1,1,n);
        while(m--){
            int op=read(),l=read(),r=read();
            if(op==1)printf("%d\n",query(1,l,r));
            else if(op==2){
                int s=read();
                update(1,l,r,s);
            }
            else modify(1,l,r);
        }
    }
    return 0;
}

2018.07.08 NOIP模拟 好数(线段树)的更多相关文章

  1. 2018.10.20 NOIP模拟 蛋糕(线段树+贪心/lis)

    传送门 听说是最长反链衍生出的对偶定理就能秒了. 本蒟蒻直接用线段树模拟维护的. 对于第一维排序. 维护第二维的偏序关系可以借助线段树/树状数组维护逆序对的思想建立权值线段树贪心求解. 代码

  2. 2018.06.29 NOIP模拟 排列(线段树)

    排列(premu.cpp) [题目描述] 对于一个 1 到 n 的排列,逆序数的定义为:排列中第 i 位 ai的逆序数就是 a1-ai-1中比 ai大的数的个数.另外用 pi表示 a1,-,ai的逆序 ...

  3. 2018.06.26 NOIP模拟 纪念碑(线段树+扫描线)

    题解: 题目背景 SOURCE:NOIP2015−GDZSJNZXSOURCE:NOIP2015-GDZSJNZXSOURCE:NOIP2015−GDZSJNZX(难) 题目描述 2034203420 ...

  4. 2018.10.12 NOIP模拟 数据结构(线段树)

    传送门 sb线段树题居然还卡常. 修改操作直接更新区间最小值和区间标记下传即可. 询问加起来最多5e65e65e6个数. 因此直接询问5e65e65e6次最小值就行了. 代码

  5. 2018.06.29 NOIP模拟 旅馆(线段树)

    旅馆 [问题描述] OIEROIEROIER 们最近的旅游计划,是到长春净月潭,享受那里的湖光山色,以及明 媚的阳光.你作为整个旅游的策划者和负责人,选择在潭边的一家著名的旅馆住 宿.这个巨大的旅馆一 ...

  6. 2018.07.08 hdu6183 Color it(线段树)

    Color it Time Limit: 20000/10000 MS (Java/Others) Memory Limit: 132768/132768 K (Java/Others) Proble ...

  7. 2018.07.08 NOIP模拟 第K小数(二分)

    第K小数 题目背景 SOURCE:NOIP2016-AHSDFZ T1 题目描述 有两个正整数数列,元素个数分别为 N 和 M .从两个数列中分别任取一个数相乘,这样一共可以得到 N*M 个数,询问这 ...

  8. 2018.07.08 NOIP模拟 ABCD(背包)

    ABCD 题目背景 SOURCE:NOIP2016-AHSDFZ T2 题目描述 有 4 个长度为 N 的数组 a,b,c,d .现在需要你选择 N 个数构成数组e ,数组e 满足 a[i]≤e[i] ...

  9. 2018.10.08 NOIP模拟 序列(主席树)

    传送门 T2防ak题? 其实也不是很难(考试时sb了). 直接变形一下求出区间长度在[l2,r2][l2,r2][l2,r2]之间,中位数≤l1−1\le l1-1≤l1−1的区间数,和区间长度在[l ...

随机推荐

  1. 简单ssh建立 (paramiko)

    SSH为建立在应用层和传输层基础上的安全协议.SSH是目前较可靠,专为远程登录会话和其他网络服务提供安全性的协议.利用SSH协议可以有效防止远程管理过程中的信息泄露问题. import paramik ...

  2. File 操作

    文件乱码 服务器地址 try-with-resource 属性文件获取 文件排序 文件过滤 文件下载 流文件传递 文件乱码: WINDOWS系统桌面默认使用GBK,Linux系统默认使用UTF-8. ...

  3. cv::Mat到YUV420的转换《转》

    某些特定场合我们会经常遇到yuv420格式的视频文件,这种视频帧无法直接用于opencv,故而,需要进行格式转换:幸运的是,opencv提供了rgb到yuv420的格式转换函数:下面给出基本用法: 函 ...

  4. Window python下载安装

    Window python下载安装 http://www.runoob.com/python/python-install.html https://pan.baidu.com/s/1MoR9nWUY ...

  5. vue-cli 上手

    1.cnpm install --global vue-cli 安装脚手架 2.vue init webpack baoge 创建 3.选择配置项 Project name (baoge): ---- ...

  6. ArcGIS案例学习笔记1_1

    ArcGIS案例学习笔记1_1 联系方式:谢老师,135_4855_4328, xiexiaokui#qq.com 时间:第一天上午 准备 0.U盘复制ArcGIS培训*** 1.练习数据不要放到桌面 ...

  7. oracle与DB2

    1.体系结构,DB2的实例和数据库分开的做法,我个人还是比较喜欢的,因为实例可以创建多个,数据库的恢复直接恢复到实例下就可以了,相对ORACLE简单多了. 2.管理工具,DB2的管理工具做得太简陋了, ...

  8. ccf认证模拟题之三---最大的矩形

    问题描述 在横轴上放了n个相邻的矩形,每个矩形的宽度是1,而第i(1 ≤ i ≤ n)个矩形的高度是hi.这n个矩形构成了一个直方图.例如,下图中六个矩形的高度就分别是3, 1, 6, 5, 2, 3 ...

  9. phpStudy5——php导入其他php文件(php文件的引入)

    前言: 通过前边几个例子,相信大家都会有一个疑惑了,就是每个请求数据库的php页面,都要写一次连接数据库的代码,这个肯定是有违代码复用原则的.那么怎么解决这个问题呢? 在php中可以通过include ...

  10. 关于Python的OSError和IOError

    参考:http://stackoverflow.com/questions/29347790/difference-between-ioerror-and-oserror 在3.x版本已经移除,剩下O ...