bzoj4869 [Shoi2017]相逢是问候
Posted 逢山开路 遇水架桥
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了bzoj4869 [Shoi2017]相逢是问候相关的知识,希望对你有一定的参考价值。
传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=4869
【题解】
发现好像没有办法普通维护。
给小盆友们江数论的时候江过x^m mod p = x^(m mod phi(p)) mod p
发现一个数进行phi操作最多log次。
暴力就行啦qwq
注意就是phi的那个最后要补一个phi[++pn] = 1。
为什么呢?因为phi(1) = 1(展开到最后,还要多展开一层(!))
那么就行啦!
复杂度不大会分析qwq
照理性分析可能是log方到log三方之间的啦
反正跑的……挺快
# include <stdio.h> # include <string.h> # include <algorithm> // # include <bits/stdc++.h> using namespace std; typedef long long ll; typedef long double ld; typedef unsigned long long ull; const int M = 5e5 + 10; # define RG register # define ST static int n, m, p, c, a[M], phi[M], pn; inline int pwr(int a, int b, int p) { int ret = 1; while(b) { if(b&1) ret = 1ll * ret * a % p; a = 1ll * a * a % p; b >>= 1; } return ret; } inline int getphi(int n) { int ret = n; for (int i=2; i*i<=n; ++i) { if(n%i!=0) continue; ret = ret/i*(i-1); while(n%i==0) n/=i; } if(n!=1) ret=ret/n*(n-1); return ret; } inline int calc(int x, int p) { int ret = x; if(ret >= phi[p]) ret = ret % phi[p] + phi[p]; while(p--) { x = ret; ret = pwr(c, x, phi[p]); if(p && !ret) ret += phi[p]; } return ret % phi[0]; } namespace SMT { # define ls (x<<1) # define rs (x<<1|1) int v[M], tms[M]; inline void build(int x, int l, int r) { if(l==r) { v[x] = a[l] % phi[0]; tms[x] = 0; return ; } int mid = l+r>>1; build(ls, l, mid); build(rs, mid+1, r); v[x] = (v[ls]+v[rs])%phi[0]; tms[x] = min(tms[ls], tms[rs]); } inline void change(int x, int l, int r, int L, int R) { if(tms[x] >= pn) return; if(l == r) { tms[x] ++; v[x] = calc(a[l], tms[x]); return ; } int mid = l+r>>1; if(L <= mid) change(ls, l, mid, L, R); if(R > mid) change(rs, mid+1, r, L, R); v[x] = (v[ls]+v[rs])%phi[0]; tms[x] = min(tms[ls], tms[rs]); } inline int query(int x, int l, int r, int L, int R) { if(L <= l && r <= R) return v[x]; int mid = l+r>>1, re=0; if(L <= mid) re += query(ls, l, mid, L, R); if(R > mid) re += query(rs, mid+1, r, L, R); return re%phi[0]; } # undef ls # undef rs } int main() { scanf("%d%d%d%d", &n, &m, &p, &c); for (int i=1; i<=n; ++i) scanf("%d", a+i); phi[0] = p; while(p != 1) { int t = getphi(p); phi[++pn] = t; p = t; } phi[++pn] = 1; SMT::build(1, 1, n); int opt, l, r; while(m--) { scanf("%d%d%d", &opt, &l, &r); if(opt==0) SMT::change(1, 1, n, l, r); else printf("%d\n", SMT::query(1, 1, n, l, r)); } return 0; }
以上是关于bzoj4869 [Shoi2017]相逢是问候的主要内容,如果未能解决你的问题,请参考以下文章