3813: 奇数国 线段树+线性筛素数+欧拉函数+乘法逆元+压位
2016-02-15 08:30
399 查看
感觉就是几个算法的叠加。。没什么思维的难度。。无脑码代码呗。
首先维护区间乘法线段树就好,然后那个存在ax+by=1的限制条件,根据裴蜀定理其实据说gcd(x,y)=1即x,y互质,那么这个可以用欧拉函数解决。然后根据欧拉函数的通式算的时候需要用到乘法逆元,范围很小这个随便求了。。至于质因子的存在情况因为不超过60个所以开一个longlong压位就好了,依旧线段树维护。
= =无脑题好无聊
首先维护区间乘法线段树就好,然后那个存在ax+by=1的限制条件,根据裴蜀定理其实据说gcd(x,y)=1即x,y互质,那么这个可以用欧拉函数解决。然后根据欧拉函数的通式算的时候需要用到乘法逆元,范围很小这个随便求了。。至于质因子的存在情况因为不超过60个所以开一个longlong压位就好了,依旧线段树维护。
= =无脑题好无聊
#include<iostream> #include<cstdio> #include<map> #define p 19961993 #define N 100000 #define ll long long #define pa pair<ll,ll> using namespace std; int l[400005],r[400005]; ll val_a[400005],val_b[400005]; int n; int prime[65]; ll inv[305]; bool flag[305]; inline int read() { int a=0,f=1; char c=getchar(); while (c<'0'||c>'9') {if (c=='-') f=-1; c=getchar();} while (c>='0'&&c<='9') {a=a*10+c-'0'; c=getchar();} return a*f; } inline void update(int k) { val_a[k]=val_a[k<<1]*val_a[k<<1|1]%p; val_b[k]=val_b[k<<1]|val_b[k<<1|1]; } void build(int k,int x,int y) { l[k]=x; r[k]=y; if (l[k]==r[k]) {val_a[k]=3; val_b[k]=2; return;} int mid=l[k]+r[k]>>1; build(k<<1,l[k],mid); build(k<<1|1,mid+1,r[k]); update(k); } inline void pre() { for (int i=2;i<=281;i++) { if (!flag[i]) prime[++prime[0]]=i; for (int j=1;j<=prime[0]&&i*prime[j]<=281;j++) { flag[i*prime[j]]=1; if (i%prime[j]==0) break; } } inv[1]=1; for (int i=2;i<=281;i++) inv[i]=(p-p/i)*inv[p%i]%p; } pa ask(int k,int x,int y) { if (l[k]==x&&r[k]==y) return make_pair(val_a[k],val_b[k]); int mid=l[k]+r[k]>>1; if (y<=mid) return ask(k<<1,x,y); else if (x>mid) return ask(k<<1|1,x,y); else { pa s1=ask(k<<1,x,mid),s2=ask(k<<1|1,mid+1,y); ll x1=s1.first*s2.first%p,x2=s1.second|s2.second; return make_pair(x1,x2); } } inline ll query(int x,int y) { pa s=ask(1,x,y); ll ans=s.first; for (int i=1;i<=60;i++) if (s.second&(1ll<<(i-1))) ans=ans*(prime[i]-1)%p*inv[prime[i]]%p; ans=(ans+p)%p; return ans; } void change(int k,int x,int val) { if (l[k]==r[k]) { val_a[k]=val; val_b[k]=0; for (int i=1;i<=60;i++) if (val%prime[i]==0) val_b[k]|=(1ll<<(i-1)); return; } int mid=l[k]+r[k]>>1; if (x<=mid) change(k<<1,x,val); else change(k<<1|1,x,val); update(k); } int main() { n=read(); pre(); build(1,1,100000); for (int i=1;i<=n;i++) { int a=read(),b=read(),c=read(); if (a==0) printf("%lld\n",query(b,c)); else change(1,b,c); } return 0; }
相关文章推荐
- usual website address
- Eclipse快捷键
- 复利不现实。
- 上周热点回顾(2.8-2.14)
- Android 知识图谱
- 折半查找法
- HDFS文档概述
- 可变参数,参数的个数不确定
- 《线程》——多线程同步实例剖析
- Android学习笔记之Serializable和Parcelable的区别
- [LeetCode 172] Factorial Trailing Zeroes
- Spring AOP(配置文件方式)
- hbase scan 的例子
- Win10/Win8.1自动维护功能怎么快速开启和关闭?
- bzoj2276 Temperature
- error at ::0 can't find referenced pointcut解决办法(转载)
- 不要放弃治疗
- 从零开始山寨Caffe·壹:仰望星空与脚踏实地
- bzoj1010 玩具装箱toy
- 卡夫卡作品研究