UESTC 87 Easy Problem With Numbers 线段树区间更新 逆元 分解质因数
2015-10-09 16:12
429 查看
UESTC 87 Easy Problem With Numbers
区间内所有元素乘以x
区间内所有元素除以x
查询区间所有元素积取余M
问题的关键是区间内所有元素除以x这个操作.
因为要取模,所以不能直接搞.
怎么办?首先我们想到逆元
但是
定理:a存在模p的乘法逆元的充要条件是gcd(a,p) = 1
于是想到了以M的素因子 分解x 最后剩下的数px肯定满足gcd(px,M) = 1
这样我们要维护的东西变成了区间内每个素因子的个数和 与 与M互质的那个数的逆元
题意:
题意非常简单,给定一个序列 和 M 三种操作区间内所有元素乘以x
区间内所有元素除以x
查询区间所有元素积取余M
思路:
线段树问题的关键是区间内所有元素除以x这个操作.
因为要取模,所以不能直接搞.
怎么办?首先我们想到逆元
但是
定理:a存在模p的乘法逆元的充要条件是gcd(a,p) = 1
于是想到了以M的素因子 分解x 最后剩下的数px肯定满足gcd(px,M) = 1
这样我们要维护的东西变成了区间内每个素因子的个数和 与 与M互质的那个数的逆元
#include <bits/stdc++.h> #define lson num<<1 #define rson num<<1|1 #define gl l,m,lson #define gr m+1,r,rson #define PARA int l=1,int r=n,int num=1 #define CLR(a) memset(a,0,sizeof(a)) using namespace std; typedef long long LL; const int MAXN = 1e4+100; int n; LL MOD; template <class T> inline void scan_d(T &ret) { char c; ret=0; while((c=getchar())<'0'||c>'9'); while(c>='0'&&c<='9') ret=ret*10+(c-'0'),c=getchar(); } void ex_gcd(LL a, LL b, LL &x, LL &y) { if(b == 0) { x = 1; y = 0; return; } ex_gcd(b, a % b, x, y); LL tmp = x; x = y; y = tmp - (a / b) * y; } LL inv(LL v) { LL x,y; ex_gcd(v,MOD,x,y); x%=MOD; while(x<0) x+=MOD; return x; } LL mod(LL a, LL b) { if(b < 0) return 0; LL ret = 1; a %= MOD; for (; b; b >>= 1, a = (a * a) % MOD) if (b & 1) ret = (ret * a) % MOD; return ret; } struct Factor { LL fac[12]; LL ret[12]; int cnt; void init(LL v) { cnt=0; for(LL i=2;i*i<=v;i++) { if(v%i==0) fac[cnt++]=i; for(;v%i==0;v/=i); } if(v!=1) fac[cnt++]=v; } void find(LL &v,int f) { for(int i=0;i<cnt;i++) { ret[i]=0; for(;v&&v%fac[i]==0;v/=fac[i]) ret[i]=ret[i]+f; } } }pf; struct SegTree { struct Node { LL l,r; LL fac[12],tag[12]; LL v,tv; bool has=0; void init(LL a,LL b) { l=a,r=b; v=1; tv=1; CLR(fac); CLR(tag); has=0; } void mark(LL *a,LL b) { tv*=b; tv%=MOD; for(int i=0;i<pf.cnt;i++) { tag[i]+=a[i]; fac[i]+=a[i]*(r-l+1); } v=v*mod(b,r-l+1); v%=MOD; has=1; } LL count() { LL ret=v%MOD; for(int i=0;i<pf.cnt;i++) ret=ret*mod(pf.fac[i],fac[i]),ret%=MOD; return ret; } void show() { printf("(%lld,%lld):%lld\n",l,r,count()); printf("v:%lld\n",v); for(int i=0;i<pf.cnt;i++) printf(" %d",fac[i]); puts(""); printf("tv:%lld\n",tv); for(int i=0;i<pf.cnt;i++) printf(" %d",tag[i]); puts("\n"); } }st[MAXN<<2]; void pushUp(int num) { for(int i=0;i<pf.cnt;i++) st[num].fac[i]=st[lson].fac[i]+st[rson].fac[i]; st[num].v=st[lson].v*st[rson].v%MOD; } void pushDown(int num) { LL l=st[num].l,r=st[num].r; if(l!=r) { if(st[num].has) { st[lson].mark(st[num].tag,st[num].tv); st[rson].mark(st[num].tag,st[num].tv); pushUp(num); CLR(st[num].tag); st[num].tv=1; } pushUp(num); } st[num].has=0; } void init(PARA) { int m=l+r>>1; st[num].init(l,r); if(l==r) { LL v; scan_d(v),pf.find(v,1); st[num].mark(pf.ret,v); } else init(gl),init(gr),pushUp(num); } void update(int a,int b,LL v,PARA) { pushDown(num); if(a<=l&&r<=b) st[num].mark(pf.ret,v); else { int m=l+r>>1; if(b<=m) update(a,b,v,gl); else if(a>m) update(a,b,v,gr); else update(a,b,v,gl),update(a,b,v,gr); pushUp(num); } } LL query(int a,int b,PARA) { pushDown(num); if(a<=l&&r<=b) return st[num].count(); else { int m=l+r>>1; LL ret; if(b<=m) ret=query(a,b,gl); else if(a>m) ret=query(a,b,gr); else ret=query(a,b,gl)*query(a,b,gr); pushUp(num); return ret%MOD; } } void show(PARA) { int m=l+r>>1; st[num].show(); if(l!=r) show(gl),show(gr); } }soul; bool DEBUG=0; void debug() { puts("______"); soul.show(); puts("______"); } int main() { if(DEBUG) freopen("v3.txt","w",stdout); int T,cas=1; scan_d(T); while(T--) { scan_d(n); scan_d(MOD); pf.init(MOD); soul.init(); int m; scan_d(m); printf("Case #%d:\n",cas++); if(DEBUG) debug(); while(m--) { char s[5]; scanf("%s",s); LL a,b,c; scan_d(a); scan_d(b); if(s[0]=='Q') printf("%lld\n",soul.query(a,b)); else { scan_d(c); int f; if(s[0]=='M') pf.find(c,1); else pf.find(c,-1),c=inv(c); soul.update(a,b,c); } if(DEBUG) debug(); } } return 0; }
相关文章推荐
- Guide: Solr performance tuning--转载
- ios上 更改 状态栏(UIStatusBar)的颜色
- 导航控制器UINavigationController
- Android UI框架基本概念
- UIButton中的三个UIEdgeInsets属性(二)
- UIButton中的三个UIEdgeInsets属性(一)
- [Phonegap+Sencha Touch] 移动开发66 sencha touch可编辑的div(ContentEditable=true)下,长按不弹出“复制粘贴”菜单的解决办法
- 【第十五篇】easyui datagrid的列编辑,同时插入两张表的数据进去
- UIButton文字居左显示
- 安卓在4.3的系统中提供了低功耗蓝牙Bluetooth Low Energy
- 五种创建UIImage的类方法
- 2015年四川省赛||弱校联萌十一大决战之强力热身 H. Range Query 二分图的最大匹配确定匹配顺序
- sublime3+quick3.5 完整使用教程
- RequireJs 入门
- SuiShenJi项目_EditText多行输入
- ExecuteNonQuery返回值问题
- 【第十四篇】easyui datagrid导出excel
- Android报错解决 UIL doesn't support scheme(protocol) by default [file:/]. You should impleme
- General Problem Solving Techniques [Intermediate-1]~D - Fabled Rooks
- Arduino uno R3 + ESP8266-01 测试例程