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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

gym 102875A -- Array(未更新完)

發布時間:2023/12/3 编程问答 36 豆豆
生活随笔 收集整理的這篇文章主要介紹了 gym 102875A -- Array(未更新完) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

gym 102875A – Array

題意:

對于一個數組a,以及數p,
q個操作
1.對于區間[l,r],里面所有數+k
2.對于區間[l,r],里面所有數 * k
3.對于區間[l,r],里面所有數變成k次冪
4.對于區間[l,r],輸出里面所有數k次冪的和
5.對于區間[l,r],輸出里面所有數的乘積
操作4和5的結果mod p
1<=n<=1e5
2<=p<=30
0<=a<=1e9
1<=q<=1e5
注:我們規定00 = 1

題解:

參考題解
參考題解
第一個題解的方法很妙,因為p的范圍很小,所以可以直接用線段樹來維護每個區間值為x的數有多少個,f數組用來記錄每個數轉移成了什么數
num[root<<1][f[root][i]] = num[root<<1][i]
第二個方法在計算快速冪時用歐拉降冪來優化下常數


4月26再看這題
在刷了很多樹之后,有些感覺。。但感覺讓自己寫還是寫不出
num[root][i]以root為根的子樹中有多少個i
f[root][i] 表示以root為根的子樹中原本的i轉移成了什么數
因為p很小,所以可以將mod值和pow值(記得取模)提前求好
代碼很妙,思路也很好,是個好題

代碼:

#include<bits/stdc++.h> using namespace std; #define G if(++ip==ie)if(fread(ip=buf,1,SZ,stdin)) #define ri register int #define iv inline void using namespace std; const int SZ=1<<19; char buf[SZ],*ie=buf+SZ,*ip=ie-1; inline int in(){G;while(*ip<'-')G;ri x=*ip&15;G;while(*ip>'-'){x*=10;x+=*ip&15;G;}return x; } const int N=1e5+5; int p; int num[N*4][35],f[N*4][35]; int tmp[35]; void push_down(int root){for(int i=0;i<p;i++){tmp[i]=num[root<<1][i];num[root<<1][i]=0;} for(int i=0;i<p;i++){num[root<<1][f[root][i]]+=tmp[i];}for(int i=0;i<p;i++){tmp[i]=num[root<<1|1][i];num[root<<1|1][i]=0;}for(int i=0;i<p;i++){num[root<<1|1][f[root][i]]+=tmp[i];}for(int i=0;i<p;i++){f[root<<1][i]=f[root][f[root<<1][i]];f[root<<1|1][i]=f[root][f[root<<1|1][i]];}for(int i=0;i<p;i++)f[root][i]=i; } int a[N]; void build(int l,int r,int root){for(int i=0;i<p;i++)f[root][i]=i;if(l==r){num[root][a[l]]=1;return ;}int mid=l+r>>1;build(l,mid,root<<1);build(mid+1,r,root<<1|1);for(int i=0;i<p;i++)num[root][i]=num[root<<1][i]+num[root<<1|1][i]; } int quik(int a,int b){int ans=1;for(;b;b>>=1,a=a*a%p)if(b&1)ans=ans*a%p;return ans;} int mod[N]; int qpow[35]; /* num[root][i]以root為根的子樹中有多少個i f[root][i] 表示以root為根的子樹中原本的i轉移成了什么數 */ void update(int l,int r,int root,int ql,int qr,int op,int v){if(l>=ql&&r<=qr){if(op==2){//mulfor(int i=0;i<p;i++){tmp[i]=num[root][i];num[root][i]=0;}for(int i=0;i<p;i++){num[root][mod[i*v]]+=tmp[i];f[root][i]=mod[f[root][i]*v];}}else if(op==1){//addfor(int i=0;i<p;i++){tmp[i]=num[root][i];num[root][i]=0;}for(int i=0;i<p;i++){num[root][mod[(i+v)]]+=tmp[i];f[root][i]=mod[(f[root][i]+v)];}}else if(op==3){//^kfor(int i=0;i<p;i++){tmp[i]=num[root][i];num[root][i]=0;}for(int i=0;i<p;i++){num[root][qpow[i]]+=tmp[i];f[root][i]=qpow[f[root][i]];}}return ;}push_down(root);int mid=l+r>>1;if(mid>=ql)update(l,mid,root<<1,ql,qr,op,v);if(mid<qr)update(mid+1,r,root<<1|1,ql,qr,op,v);for(int i=0;i<p;i++)num[root][i]=num[root<<1][i]+num[root<<1|1][i]; } int ans[35]; void query(int l,int r,int root,int ql,int qr){if(l>=ql&&r<=qr){for(int i=0;i<30;i++)ans[i]+=num[root][i];return ;}push_down(root);int mid=l+r>>1;if(mid>=ql)query(l,mid,root<<1,ql,qr);if(mid<qr)query(mid+1,r,root<<1|1,ql,qr); } int main() {int n;n=in(),p=in();for(int i=1;i<=n;i++)a[i]=in(),a[i]%=p;for(int i=0;i<35*35;i++)mod[i]=i%p;build(1,n,1);int q;q=in();while(q--){int op,l,r,k;op=in(),l=in(),r=in(),k=in();if(op<=2)k%=p;else if(op==3){for(int i=0;i<p;i++)qpow[i]=quik(i,k);}if(op<=3)update(1,n,1,l,r,op,k);else {for(int i=0;i<p;i++)ans[i]=0;query(1,n,1,l,r);if(op==4){int sum=0;for(int i=0;i<p;i++)sum=(sum+quik(i,k)*ans[i])%p;printf("%d\n",sum);}else {int sum=1;for(int i=0;i<p;i++)sum=sum*quik(i,ans[i])%p;printf("%d\n",sum);}}}return 0; }

總結

以上是生活随笔為你收集整理的gym 102875A -- Array(未更新完)的全部內容,希望文章能夠幫你解決所遇到的問題。

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