博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
[BZOJ 4869][SHOI&SXOI2017]相逢是问候(扩展欧拉定理+线段树)
阅读量:6368 次
发布时间:2019-06-23

本文共 3040 字,大约阅读时间需要 10 分钟。

Description

Informatik verbindet dich und mich.
信息将你我连结。B君希望以维护一个长度为n的数组,这个数组的下标为从1到n的正整数。一共有m个操作,可以
分为两种:0 l r表示将第l个到第r个数(al,al+1,...,ar)中的每一个数ai替换为c^ai,即c的ai次方,其中c是
输入的一个常数,也就是执行赋值ai=c^ai1 l r求第l个到第r个数的和,也就是输出:sigma(ai),l<=i<=rai因为
这个结果可能会很大,所以你只需要输出结果mod p的值即可。

Solution

强迫症非要把这两道题放在一起…

学习了一下扩展欧拉定理

a^b≡x(mod m) 求x

gcd(a,m)=1,欧拉定理:a^b≡a^(b%φ(m))(mod m)

gcd(a,m)>1,且b>φ(m),扩展欧拉定理:a^b≡a^(b%φ(m)+φ(m))(mod m)

(b<=φ(m)时,直接用a^b求就可以了)

考试的时候数据出了一点问题啊…不过及时解决了也没造成太大影响

数据出错的原因据说是因为没有多展开phi[1]=1这一层?

2017.07.04:如果a和m互质的话是只能用欧拉定理而不能用ext的,所以一定要加一个判断,大家如果没有A掉问题可能是出在这里…

另外在Exbilar同学的提醒下代码做出了一些改动

#include
#include
#include
#include
#define MAXN 50005using namespace std;typedef long long LL; int n,m,P,c,a[MAXN],phi[MAXN],k;struct Node{ int l,r,cnt; LL sum;}t[MAXN*4];inline int read(){ int x=0,f=1;char c=getchar(); while(c<'0'||c>'9'){
if(c=='-')f=-1;c=getchar();} while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();} return x*f;}inline int get_phi(int x){ int res=x; for(int i=2;i*i<=x;i++) { if(x%i==0) { res=res/i*(i-1); while(x%i==0)x/=i; } } if(x!=1)res=res/x*(x-1); return res;}inline LL gcd(LL a,LL b){
return b?gcd(b,a%b):a;}void build(int idx,int l,int r){ t[idx].l=l,t[idx].r=r,t[idx].cnt=0; if(l==r){t[idx].sum=a[l]%phi[0];return;} int mid=(l+r)>>1; build(idx<<1,l,mid); build(idx<<1|1,mid+1,r); t[idx].sum=(t[idx<<1].sum+t[idx<<1|1].sum)%phi[0];}int query(int idx,int l,int r){ if(l<=t[idx].l&&r>=t[idx].r)return t[idx].sum; int mid=(t[idx].l+t[idx].r)>>1; if(r<=mid)return query(idx<<1,l,r); else if(l>mid)return query(idx<<1|1,l,r); else return (query(idx<<1,l,r)+query(idx<<1|1,l,r))%phi[0];}inline LL pow(LL a,LL n,LL mod){ LL res=1; while(n) { if(n&1)res=(res*a)%mod; a=(a*a)%mod; n>>=1; } return res%mod;}inline LL modify(int cnt,LL num){ LL res=num; if(res>=phi[cnt])res=res%phi[cnt]+phi[cnt]; for(int i=cnt;i>0;i--) { res=pow(c,res,phi[i-1]); if(gcd(c,res)!=1)res+=phi[i-1]; } return res%phi[0];} void change(int idx,int l,int r){ if(t[idx].cnt>=k)return; if(t[idx].l==t[idx].r) { t[idx].cnt++; t[idx].sum=modify(t[idx].cnt,a[t[idx].l]); return; } int mid=(t[idx].l+t[idx].r)>>1; if(r<=mid)change(idx<<1,l,r); else if(l>mid)change(idx<<1|1,l,r); else change(idx<<1,l,r),change(idx<<1|1,l,r); t[idx].sum=(t[idx<<1].sum+t[idx<<1|1].sum)%phi[0]; t[idx].cnt=min(t[idx<<1].cnt,t[idx<<1|1].cnt);}int main(){ n=read(),m=read(),P=read(),c=read(); for(int i=1;i<=n;i++)a[i]=read(); k=0;phi[0]=P; while(P!=1) { phi[++k]=get_phi(P); P=phi[k]; } phi[++k]=1; build(1,1,n); for(int i=1;i<=m;i++) { int opt=read(),l=read(),r=read(); if(!opt)change(1,l,r); else printf("%d\n",query(1,l,r)); } return 0;}

 

转载于:https://www.cnblogs.com/Zars19/p/6791821.html

你可能感兴趣的文章
Android打地鼠游戏的修改和优化
查看>>
Java异常
查看>>
map、reduce、filter、for...of、for...in等总结
查看>>
html2canvas-实现页面截图
查看>>
入门 | 从文本处理到自动驾驶:机器学习最常用的50大免费数据集
查看>>
笔记-从源码角度分析alloc与init的底层
查看>>
消除GitHub上的历史记录
查看>>
自学 JAVA 的几点建议
查看>>
第十三天-企业应用架构模式-对象-关系元数据映射模式
查看>>
k8s与HPA--通过 Prometheus adaptor 来自定义监控指标
查看>>
Python 比特币教程之二: 机器人收发比特币
查看>>
虎牙直播在微服务改造方面的实践和总结
查看>>
怎样将优酷网站下载的视频KUX转MP4格式
查看>>
MongoDB 分组统计
查看>>
二进制状态码
查看>>
Vue 中 CSS 动画原理
查看>>
关于 Promise 的 9 个提示
查看>>
算法复习
查看>>
安卓中高级开发面试知识点之——缓存
查看>>
Java的初始化顺序
查看>>