国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 開發設計 > 正文

[SD2014集訓]查詢(分塊+數學相關)

2019-11-14 11:38:09
字體:
來源:轉載
供稿:網友

題目描述

這里寫圖片描述 這里寫圖片描述 這里寫圖片描述 這里寫圖片描述

題解

看模數那么奇怪找一下規律看看有沒有奇怪的性質 發現每一個數立方48次后回到原數 線段樹不如分塊好寫 維護每個數立方k次后得到的數,每一個塊所有的數分別立方k次后的和 修改時,對于整塊記錄立方的次數,其余的暴力重構 重構即把塊內的點維護的立方旋轉t次,然后重新計算和 查詢時,整塊直接查詢,其余暴力 時間復雜度O(m(block+n?szblock)),可以發現當block=n?sz?????√時有最小值,O(mn?sz?????√)≈2.19s

代碼

#include<algorithm>#include<iostream>#include<cstring>#include<cstdio>#include<cmath>using namespace std;#define LL long long#define Mod 329701061#define sz 48#define N 100005char opt;int n,m,x,y,block,tot;int t[N],num[N],l[N],r[N];LL a[N],cub[N][sz],Cub[N][sz],s[sz];void init(){ for (int i=1;i<=n;++i) { cub[i][0]=a[i]; for (int j=1;j<sz;++j) cub[i][j]=cub[i][j-1]*cub[i][j-1]%Mod*cub[i][j-1]%Mod; } for (int i=1;i<=tot;++i) for (int j=0;j<sz;++j) for (int k=l[i];k<=r[i];++k) { Cub[i][j]+=cub[k][j]; if (Cub[i][j]>=Mod) Cub[i][j]-=Mod; }}void move(int id,int rad){ if (!rad) return; for (int i=0;i<rad;++i) s[i]=cub[id][i]; for (int i=rad;i<sz;++i) cub[id][i-rad]=cub[id][i]; for (int i=0;i<rad;++i) cub[id][i+sz-rad]=s[i];}void calc(int id){ for (int i=0;i<sz;++i) { Cub[id][i]=0; for (int j=l[id];j<=r[id];++j) { Cub[id][i]+=cub[j][i]; if (Cub[id][i]>=Mod) Cub[id][i]-=Mod; } }}void change(int x,int y){ if (num[x]==num[y]) { for (int i=l[num[x]];i<x;++i) move(i,t[num[x]]); for (int i=y+1;i<=r[num[y]];++i) move(i,t[num[x]]); ++t[num[x]];if (t[num[x]]==sz) t[num[x]]=0; for (int i=x;i<=y;++i) move(i,t[num[x]]); t[num[x]]=0; calc(num[x]); return; } if (x==l[num[x]]) x=num[x]; else { for (int i=l[num[x]];i<x;++i) move(i,t[num[x]]); ++t[num[x]];if (t[num[x]]==sz) t[num[x]]=0; for (int i=x;i<=r[num[x]];++i) move(i,t[num[x]]); t[num[x]]=0; calc(num[x]); x=num[x]+1; } if (y==r[num[y]]) y=num[y]; else { for (int i=y+1;i<=r[num[y]];++i) move(i,t[num[y]]); ++t[num[y]];if (t[num[y]]==sz) t[num[y]]=0; for (int i=l[num[y]];i<=y;++i) move(i,t[num[y]]); t[num[y]]=0; calc(num[y]); y=num[y]-1; } for (int i=x;i<=y;++i) { ++t[i]; if (t[i]==sz) t[i]=0; }}LL query(int x,int y){ LL ans=0; if (num[x]==num[y]) { for (int i=x;i<=y;++i) { ans+=cub[i][t[num[x]]]; if (ans>=Mod) ans-=Mod; } return ans; } if (x==l[num[x]]) x=num[x]; else { for (int i=x;i<=r[num[x]];++i) { ans+=cub[i][t[num[x]]]; if (ans>=Mod) ans-=Mod; } x=num[x]+1; } if (y==r[num[y]]) y=num[y]; else { for (int i=l[num[y]];i<=y;++i) { ans+=cub[i][t[num[y]]]; if (ans>=Mod) ans-=Mod; } y=num[y]-1; } for (int i=x;i<=y;++i) { ans+=Cub[i][t[i]]; if (ans>=Mod) ans-=Mod; } return ans;}int main(){ scanf("%d",&n); for (int i=1;i<=n;++i) scanf("%I64d",&a[i]); block=n/floor(sqrt(n*sz)); if (!block) ++block; tot=(n-1)/block+1; for (int i=1;i<=n;++i) { num[i]=(i-1)/block+1; if (num[i]!=num[i-1]) r[num[i-1]]=i-1,l[num[i]]=i; } r[tot]=n; init(); scanf("%d",&m); for (int i=1;i<=m;++i) { opt=getchar(); while (opt!='C'&&opt!='Q') opt=getchar(); scanf("%d%d",&x,&y); if (x>y) swap(x,y); if (opt=='C') change(x,y); else printf("%I64d/n",query(x,y)); }}

總結

卡常數技巧 ①分塊大小nn?sz√ ②加法的取模改成加減 ③盡量不用乘法用加減


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 湖北省| 曲靖市| 大关县| 怀集县| 咸丰县| 科尔| 宜城市| 措美县| 鄢陵县| 彰化县| 邵阳市| 屏山县| 广元市| 洪江市| 瑞昌市| 缙云县| 娱乐| 来凤县| 鹤岗市| 安康市| 北碚区| 手游| 桂阳县| 西充县| 大关县| 永平县| 法库县| 五大连池市| 盐源县| 海丰县| 瑞昌市| 吉林省| 四子王旗| 望江县| 通辽市| 三江| 农安县| 肇东市| 南城县| 渝北区| 上栗县|