[LNOI] 相逢是问候 || 扩展欧拉函数+线段树
原题为2017六省联考的D1T3
给出一个序列,m次操作,模数p和参数c
操作分为两种:
1、将[l,r]区间内的每个数x变为\(c^x\)
2、求[l,r]区间内数的和%p
首先,我们要了解一些数论姿势:
1、扩展欧拉定理
//我们熟知的费马小定理用于p是质数,欧拉定理用于a,p互质,而这道题都不满足这个限制
当\((b>=\phi(p))\)时,\(a^b=a^{b\mod \phi(p) + \phi(p)}\)
2、(其实不算数论姿势)一个数最多经过log此\(\phi\)就会变成1
所以我们发现,一个数在经过几次变化后,指数永远是\(x\mod1+1\),也就是1,它就再也不变了!
//上面这里不理解的话,可以考虑这样一道题
//给定一个长度为n的序列a,每次询问区间[l,r] \(a_l^{a_{l+1}^{…}}\)的值。\(n<=10^5,m<=10^9\)
//原题应该是叫power tower
所以我们建一棵线段树,维护当前区间和和这个区间中被修改的最小次数。
预处理出对于mod p来讲,几次后一定会不变,记为k。每次修改将当前位置的修改次数++。如果这个区间的最小修改次数>=k,那么就不需要修改了,否则暴力修改。
因为每次的修改次数不一样,所以要用初值a[i]计算times后当前数会变为什么。
因为有n个数,每个数会被暴力修改\(\log(p)\)次,每次修改是\(\log(n)\)的,再乘上快速幂的复杂度\(\log\)就是\(O(nlog^3)\)
这样基本能过了,但是被卡常的话就不稳了。可以考虑预处理c的快速幂,反正c是固定的……
//bzoj不预处理就能过,洛谷过不了(也可能是博主写的比较菜)
贴一份没有预处理的代码
#include<cstdio>
#include<algorithm>
#define N 50010
#define M 10010
typedef long long ll;
using namespace std;
int a[N],n,m,prime[N],tot,p[N],P,c,op,l,r,k,MOD;
bool np[N];
struct hhh
{
int l,r,sum,is;
}tre[4*N];
int read()
{
int ans=0,fu=1;
char j=getchar();
for (;j<'0' || j>'9';j=getchar()) if (j=='-') fu=-1;
for (;j>='0' && j<='9';j=getchar()) ans*=10,ans+=j-'0';
return ans*fu;
}
int ksm(int x,int y,int mo,bool &flag)
{
int ret=1;
bool big=0;
while (y)
{
if (y&1)
{
flag|=big|((ll)ret*x>=mo);
ret=(ll)ret*x%mo;
}
if ((ll)x*x>=mo) big=1;
x=(ll)x*x%mo;
y>>=1;
}
return ret;
}
void build(int i,int l,int r)
{
tre[i].l=l;tre[i].r=r;tre[i].is=0;
if (l==r)
{
tre[i].sum=a[l]%P;
return ;
}
int mid=(l+r)>>1;
build(i*2,l,mid);
build(i*2+1,mid+1,r);
tre[i].sum=(tre[i*2].sum+tre[i*2+1].sum)%P;
}
int calc(int x,int dep)
{
int ret=x;
if (ret>=p[dep]) ret=ret%p[dep]+p[dep];
while (dep)
{
dep--;
bool flag=0;
ret=ksm(c,ret,p[dep],flag);
if (flag) ret+=p[dep];
}
return ret%P;
}
void modify(int i,int l,int r)
{
if (l>tre[i].r || r<tre[i].l) return ;
if (tre[i].is>=k) return ;
if (tre[i].l==tre[i].r)
{
tre[i].is++;
tre[i].sum=calc(a[tre[i].l],tre[i].is);
return ;
}
modify(i*2,l,r);
modify(i*2+1,l,r);
tre[i].sum=(tre[i*2].sum+tre[i*2+1].sum)%P;
tre[i].is=min(tre[i*2].is,tre[i*2+1].is);
}
int query(int i,int l,int r)
{
if (l>tre[i].r || r<tre[i].l) return 0;
if (tre[i].l>=l && tre[i].r<=r) return tre[i].sum;
return (query(i*2,l,r)+query(i*2+1,l,r))%P;
}
int phi(int n)
{
int res=n,a=n;
for(int i=2; i*i<=a; i++)
if(a%i==0)
{
res=res/i*(i-1);
while (a%i==0) a/=i;
}
if (a>1) res=res/a*(a-1);
return res;
}
int main()
{
n=read();m=read();P=read();c=read();
for (int i=1;i<=n;i++) a[i]=read();
p[0]=P;
while (p[k]!=1) { ++k; p[k]=phi(p[k-1]); }
p[++k]=1;
build(1,1,n);
while (m--)
{
op=read();l=read();r=read();
if (op) printf("%d\n",query(1,l,r));
else modify(1,l,r);
}
return 0;
}
[LNOI] 相逢是问候 || 扩展欧拉函数+线段树的更多相关文章
- LOJ #2142. 「SHOI2017」相逢是问候(欧拉函数 + 线段树)
题意 给出一个长度为 \(n\) 的序列 \(\{a_i\}\) 以及一个数 \(p\) ,现在有 \(m\) 次操作,每次操作将 \([l, r]\) 区间内的 \(a_i\) 变成 \(c^{a_ ...
- bzoj4869: [Shoi2017]相逢是问候(欧拉函数+线段树)
这题是六省联考的...据说数据还出了点锅,心疼六省选手QAQ 首先要知道扩展欧拉定理... 可以发现每次区间操作都会使模数进行一次phi操作,而一个数最多取logp次phi就会变成1,这时后面的指数就 ...
- LightOJ 1370 Bi-shoe and Phi-shoe 欧拉函数+线段树
分析:对于每个数,找到欧拉函数值大于它的,且标号最小的,预处理欧拉函数,然后按值建线段树就可以了 #include <iostream> #include <stdio.h> ...
- loj1370(欧拉函数+线段树)
传送门:Bi-shoe and Phi-shoe 题意:给出多个n(1<=n<=1e6),求满足phi(x)>=n的最小的x之和. 分析:先预处理出1~1e6的欧拉函数,然后建立一颗 ...
- [BZOJ4026]dC Loves Number Theory 欧拉函数+线段树
链接 题意:给定长度为 \(n\) 的序列 A,每次求区间 \([l,r]\) 的乘积的欧拉函数 题解 考虑离线怎么搞,将询问按右端点排序,然后按顺序扫这个序列 对于每个 \(A_i\) ,枚举它的质 ...
- 【bzoj4869】[Shoi2017]相逢是问候 扩展欧拉定理+并查集+树状数组
题目描述 Informatik verbindet dich und mich. 信息将你我连结. B君希望以维护一个长度为n的数组,这个数组的下标为从1到n的正整数.一共有m个操作,可以分为两种:0 ...
- BZOJ 4034: [HAOI2015]树上操作 [欧拉序列 线段树]
题意: 操作 1 :把某个节点 x 的点权增加 a . 操作 2 :把某个节点 x 为根的子树中所有点的点权都增加 a . 操作 3 :询问某个节点 x 到根的路径中所有点的点权和. 显然树链剖分可做 ...
- BZOJ 4034 树上操作(树的欧拉序列+线段树)
刷个清新的数据结构题爽一爽? 题意: 有一棵点数为 N 的树,以点 1 为根,且树点有边权.然后有 M 个 操作,分为三种: 操作 1 :把某个节点 x 的点权增加 a . 操作 2 :把某个节点 x ...
- BZOJ 4034 [HAOI2015]树上操作(欧拉序+线段树)
题意: 有一棵点数为 N 的树,以点 1 为根,且树点有边权.然后有 M 个 操作,分为三种: 操作 1 :把某个节点 x 的点权增加 a . 操作 2 :把某个节点 x 为根的子树中所有点的点权都增 ...
随机推荐
- vs2015 mvc项目数据迁移报错
第一次做个mvc项目玩玩,然后需要数据迁移,也没做过,就百度找怎么数据迁移, 找到的方法是: 如果数据是在类库项目里就在‘程序包管理控制台’输入:enable-migrations -ContextT ...
- ES2015学习笔记
ECMA6学习笔记 参考资料 ECMAScript6入门:http://es6.ruanyifeng.com/ 官方文档:https://babeljs.io/learn-es2015/ 开发软件:W ...
- thinkphp5保存远程图片到本地
代码 protected function saveImg($imgUrl){ $ext=strrchr($imgUrl,'.'); if(!in_array($ext,['.jpg','.png', ...
- Linux命令应用大词典-第41章 MySQL数据库
41.1 mysqld_safe:MySQL服务器启动脚本 41.2 mysql_install_db:初始化MySQL数据目录 41.3 mysqlshow:显示MySQL数据库结构 41.4 my ...
- 使用jenkins构建一个maven项目
1.登陆到jenkins首页,创建项目-->选择maven-->输入项目名称-->选择项目类型 2.进入项目配置:{先写一下项目描述和设置下保留的历史构建,然后向下拉} 找到源吗管理 ...
- Unity编辑器 - 资源修改立即写入磁盘AssetDataBase.SaveAssets()
Unity编辑器 - 资源修改立即写入磁盘AssetDataBase.SaveAssets() 在编写编辑器时,如果需要修改Unity序列化资源(如Prefab,美术资源,ScriptableObje ...
- [CodeForce455A]Boredom
题面描述 Alex doesn't like boredom. That's why whenever he gets bored, he comes up with games. One long ...
- 100. Remove Duplicates from Sorted Array && 101. Remove Duplicates from Sorted Array II [easy]
这两题类似,所以放在一起,先看第一题: Description Given a sorted array, remove the duplicates in place such that each ...
- ionic 提示框
html文件 <ion-header> <ion-navbar> <ion-title>Toast</ion-title> </ion-navba ...
- git revert 与 git reset
Git版本回滚之 git revert 与 git reset 在使用 git 的时候,如果错误push之后,经常会回滚版本. git的回滚有两种方式: revert命令:这种方式,是用一种反向的 p ...