日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

【SHOI2017】相逢是问候【扩展欧拉定理】【复杂度分析】【线段树】

發布時間:2023/12/3 编程问答 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【SHOI2017】相逢是问候【扩展欧拉定理】【复杂度分析】【线段树】 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

題意:給定一個長度為 nnn 的序列 aia_iai?,維護 mmm 次操作:

  • 區間執行 ai←caia_i \leftarrow c^{a_i}ai?cai?
  • 區間求和 模 ppp
  • 其中 p,cp,cp,c 對所有操作相同。

    n,m≤5×104,p≤108n,m\leq 5\times 10^4,p\leq 10^8n,m5×104,p108

    不建議寫,真的浪費生命

    根據擴展歐拉定理,顯然修改 O(log?p)O(\log p)O(logp) 次就沒用了,所有數總共只會修改 O(nlog?P)O(n\log P)O(nlogP) 次。

    但是暴力的話循環是占復雜度的,我們需要快速判斷某個區間是否還需要修改。

    似乎就只能線段樹了?

    暴力預處理出每個數 φ60\varphi \text{ } 60φ?60 次內的結果,然后線段樹維護區間修改次數最小值和當前的區間和。修改的時候如果當前區間最小修改次數達到 606060 就退出,否則暴力遞歸。

    復雜度 O(nlog?2P)O(n\log^2 P)O(nlog2P) ,會被卡,根號預處理快速冪可以 O(nlog?P)O(n\log P)O(nlogP)

    聽上去還挺美好,然而這題最惡心的地方在判斷擴展歐拉定理的適用條件……

    方法是在快速冪(或預處理冪)的時候記錄是否取過模。

    Q:如何證明不會出現 x>φ(p),cx%φ(p)+φ(p)<px>\varphi (p),c^{x \%\varphi(p)+\varphi(p)}<px>φ(p),cx%φ(p)+φ(p)<p ,然后繼續迭代的時候崩掉的情況?

    A:實際上 cφ(p)≥pc^{\varphi(p)} \geq pcφ(p)p 一般都是對的。

    考慮計算 φ(p)\varphi(p)φ(p) 的一個很松的下界:φ(p)\varphi(p)φ(p) 考慮了每個質因子 xxx ,然后 p←p×x?1xp\leftarrow p\times \dfrac {x-1}xpp×xx?1?

    根據糖水原理,這個 xxx 越小效果會越明顯。而 xxx 小的時候能得到的質因子也會更多。

    10810^8108 以內的數最多只有 888 個質因子,所以可以估算一個下界 φ(p)p≥12×23×45×?×1819≈0.17\dfrac{\varphi(p)}{p}\geq\dfrac 12 \times \dfrac 23\times \dfrac 45\times \dots\times \dfrac {18}{19} \approx 0.17pφ(p)?21?×32?×54?×?×1918?0.17

    相當于要證明: 2p/7≥p2^{p/7}\geq p2p/7p ,前者增長遠快于后者,ppp 足夠大(也就幾十)的時候該式成立。

    小數據暴力打表知只有個 p=6p=6p=6 ,但 666 只能取 222φ\varphiφ ,所以也崩不了

    證畢

    #include <iostream> #include <cstdio> #include <cstring> #include <cctype> #include <vector> #include <bitset> #include <utility> #define MAXN 50005 #define re register using namespace std; typedef long long ll; int n,q,c,flag; inline int mul(const int& a,const int& b,const int& MOD) {ll c=(ll)a*b;if (c>=MOD) flag=1;return c%MOD; } int m[60],len; typedef pair<int,int> pi; const int N=2e4; pi p1[60][N+5],p2[60][N+5];//i,i*10000 inline void init() {for (int T=0;T<=len;T++){p1[T][0]=p2[T][0]=make_pair(1,0);flag=0;for (int i=1;i<N;i++) p1[T][i].first=mul(p1[T][i-1].first,c,m[T]),p1[T][i].second=flag;p2[T][1].first=mul(p1[T][N-1].first,c,m[T]),p2[T][1].second=flag;for (int i=2;i<=N;i++) p2[T][i].first=mul(p2[T][i-1].first,p2[T][1].first,m[T]),p2[T][i].second=flag;} } inline int qpow(int p,int i) {pi x=p1[i][p%N],y=p2[i][p/N];flag|=(x.second|y.second);return mul(x.first,y.first,m[i]); } inline int calcphi(int x) {int ans=1;for (int i=2;i*i<=x;i++)if (x%i==0){ans*=i-1,x/=i;while (x%i==0) ans*=i,x/=i;}if (x>1) ans*=x-1;return ans; } int a[MAXN][60]; #define lc p<<1 #define rc p<<1|1 int sum[MAXN<<2],mcnt[MAXN<<2]; inline void update(int p){mcnt[p]=min(mcnt[lc],mcnt[rc]),sum[p]=(sum[lc]+sum[rc])%m[0];} void build(int p,int l,int r) {if (l==r){scanf("%d",&a[l][0]);for (int i=1;i<=len;i++){flag=0;int x=a[l][0];for (int j=i;j>=1;j--) x=qpow(x+m[j]*flag,j-1);a[l][i]=x;}sum[p]=a[l][0];return;}int mid=(l+r)>>1;build(lc,l,mid);build(rc,mid+1,r);update(p); } void modify(int p,int l,int r,int ql,int qr) {if (qr<l||r<ql) return;if (mcnt[p]>=len) return;if (l==r) return (void)(sum[p]=a[l][++mcnt[p]]);int mid=(l+r)>>1;modify(lc,l,mid,ql,qr),modify(rc,mid+1,r,ql,qr);update(p); } int query(int p,int l,int r,int ql,int qr) {if (qr<l||r<ql) return 0;if (ql<=l&&r<=qr) return sum[p];int mid=(l+r)>>1;return (query(lc,l,mid,ql,qr)+query(rc,mid+1,r,ql,qr))%m[0]; } int main() {scanf("%d%d%d%d",&n,&q,&m[0],&c);for (len=1;(m[len]=calcphi(m[len-1]))>1;++len);m[++len]=1;init();build(1,1,n);while (q--){int t,l,r;scanf("%d%d%d",&t,&l,&r);if (t==0) modify(1,1,n,l,r);else printf("%d\n",query(1,1,n,l,r));}return 0; }

    總結

    以上是生活随笔為你收集整理的【SHOI2017】相逢是问候【扩展欧拉定理】【复杂度分析】【线段树】的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。