【JZOJ100045】好数

博客详细介绍了如何解决好数问题,利用线段树和打表的方法。好数定义为2的幂、质数或特定情况下的数字,如0、1、6。在给定的N个非负整数上,需要执行询问好数数量、区间取余和修改数值的操作。通过分析,发现取模后每个位置的数变化不大,因此使用线段树能有效处理区间操作,确保算法在限制时间内运行完成。

description

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


analysis

  • 正解线段树+打表找规律

  • 打表易知好数是222的幂或是质数,还有0,1,60,1,60,1,6

  • 222的幂的等差数列公差为222,质数的公差为111666例外

  • 打一棵线段树,暴力修改是70pts70pts70pts,问题是取模不能区间操作

  • 想一下,每个数被模以后一定小于等于原先的121\over 221,所以可以保证每个位置的数除了被修改就很少再被模

  • 那么对于取模区间的操作,先O(log⁡2n)O(\log_2n)O(log2n)找出组成区间的节点,再暴力向下寻找和修改

  • 寻找的时候注意对于一段区间,如果区间的最大值已经大于模数,就可以returnreturnreturn

  • 所以跑得过去


code

#pragma GCC optimize("O3")
#pragma G++ optimize("O3")
#include<stdio.h>
#include<string.h>
#include<algorithm>
#define MAXN 100005
#define MAXNUM 1000005
#define ll long long
#define reg register ll
#define fo(i,a,b) for (reg i=a;i<=b;++i)
#define fd(i,a,b) for (reg i=a;i>=b;--i)
#define O3 __attribute__((optimize("-O3")))

using namespace std;

ll a[MAXN],p[MAXNUM],tr[MAXN*4],mx[MAXN*4];
bool bz[MAXNUM];
ll n,m,tot;

O3 inline ll read()
{
   
   
	ll x=0,f=1;char ch=getchar();
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值