JZOJ4638 第三條跑道

2021-07-15 03:05:40 字數 2913 閱讀 3662

這題碼農,表示又被出題人虐了。

我們發現ai

以及x

於是我們用線段樹,對於每個區間記錄109個質數被該區間多少個數包含。

由於要區間修改,我們再記錄109個la

zy,表示該區間該質數還要下傳多少次。

那麼,現在我們知道φ(

n)=n

∏mi=

1(1−

1pi)

(pi 表示的

n 質因數,

m表示質因數的種數)。

觀察上面的式子,乙個很顯然的結論是φ(

pn)=

pφ(n

)(p|

n)(這裡

p 是質因數)

那如果p不是n

的質因數呢?那麼φ

(pn)

=p(1

−1p)

φ(n)

=(p−

1)φ(

n)。那麼至於區間乘上乙個數

x ,先給它分解質因數,得出∏m

i=1x

kii=

x 對於乙個質因數xi

,我們已知該區間有ax

i 個數包含它,那麼它們對尤拉積的貢獻為:xa

xii 。

但是,沒有包含的怎麼辦?由上可得,沒有包含的將乘上乙個(x

i−1)

,所以該區間沒有被包含的對尤拉積的貢獻就為:(x

i−1)

r−l+

1−ax

i 。

最後給修改的區間打上la

zy標記即可。

但是,怎樣下傳標記?

我們對於乙個區間有la

zyi 表示第

i 個質數還要下傳多少次。那麼,我們先給這個區間下傳一次,具體下傳請看上述修改部分。然後,由於還要下傳(l

azyi

−1)次,而且因為已經下傳過一次,所以整個區間都有包含了第

i 個質數,剩下的貢獻就為:(p

rr−l

+1i)

lazy

i−1(這裡pr

i 表示第

i 個質數)。

對於查詢,直接找到區間尤拉積即可。

時間複雜度:o(

109nlo

g22n

) 然而,這題看似容易,實際上打對調對需要花費大量時間。

可以打乙個線性篩法求

φ 來方便除錯。

#include

#include

#include

#define fo(i,j,k) for(int i=j;i<=k;i++)

#define fd(i,j,k) for(int i=j;i>=k;i--)

#define n 10010

#define m 601

#define mo 100000007

#define ll long long

using namespace std;

int pr[m],cnt=0,phi[m];

int a[n];

bool bz[m];

struct nodetr[n*4];

int ph[n],s1[n],s2[n];

int ls[120];

intmap[m];

ll pow(ll m,int n)

return b;

}void pre()

else phi[i*pr[j]]=phi[i]*(pr[j]-1);}}

}void get(int v,int

x) }

if(x>1) tr[v].a[map[x]]=1;

}void getlazy(int v,int

x) }

if(x>1) tr[v].lz[map[x]]++,ls[map[x]]++;

}void put(int v,int l,int r)

}void build(int v,int l,int r)

int mid=(l+r)/2;

build(v*2,l,mid);

build(v*2+1,mid+1,r);

fo(i,1,109)

tr[v].a[i]=tr[v*2].a[i]+tr[v*2+1].a[i];

tr[v].s=tr[v*2].s

*tr[v*2+1].s

%mo;

}void change(int v,int l,int r,int

x,int

y,int p)

return;

}put(v,l,r);

int mid=(l+r)/2;

if(y

<=mid) change(v*2,l,mid,x,y,p);

else

if(x>mid) change(v*2+1,mid+1,r,x,y,p);

else

fo(i,1,109)

tr[v].a[i]=tr[v*2].a[i]+tr[v*2+1].a[i];

tr[v].s=tr[v*2].s

*tr[v*2+1].s

%mo;

}ll ans=1;

void find(int v,int l,int r,int

x,int

y) int mid=(l+r)/2;

put(v,l,r);

if(y

<=mid) find(v*2,l,mid,x,y);

else

if(x>mid) find(v*2+1,mid+1,r,x,y);

else

}int main()

else}}

普及 模擬 開關燈泡(jzoj第三題)

題目 description 乙個房間裡有n盞燈泡,一開始都是熄著的,有1到n個時刻,每個時刻i,我們會將i的倍數的燈泡改變狀態 即原本開著的現將它熄滅,原本熄滅的現將它點亮 問最後有多少盞燈泡是亮著的。input 乙個數n output m,表示最後有m盞是亮著的 sample input sam...

JZOJ 7 7C組第三題 頁

給出奇數個數,每次把它中間的數取出來放到最左邊或最右邊,求出最少取多少次可以讓這些數是從小到大的。bfs hash判重。每次左邊右邊操作一次,判斷之前有沒有出現過了,沒有就入隊。include define maxn 300017 using namespace std int n,state 10...

JZOJ 7 9C組第三題 排列的編碼

給出乙個長度為n序列,求出它在n的全排列中是第幾個。這道題要找規律,設ml i ml i 為第i i 位後面有幾個數比第 i role presentation style position relative i i位小,通過一系列操作 詳見某蒟佬 可以得到答案an s an s ml i n i ...