題目
發現自己一年之前非常垃圾
題目大意是給你乙個\(n\)個點的環,給每個點乙個\([1,a_i]\)的取值,並且滿足環上任意相連兩點權值不能相等,求方案數
考慮斷環為鏈,發現不大會
不妨考慮所有\(a_i\)均相等的情況,設\(m=a_i\)
對於第乙個點,有\(m\)種選擇,其後每乙個點的取值都不能和上乙個相等,即\(m-1\)種選擇,於是整個環就是\(m(m-1)^\)
嗎?顯然不是,這樣我們不能保證\(1\)號點和\(n\)號點的取值不相等。設\(f_i\)表示\(1\)號點恰好和\(n-i+1\)到\(n\)號點取值相等的情況,我們算的\(m(m-1)^\)其實等於\(f_0+f_1\)
考慮如何消掉\(f_1\),我們可以強行將\(n\)和\(1\)取值相同,其餘點還是不能和前乙個點取值相等,方案數是\(m(m-1)^=f_1+f_2\);更一般的\(m(m-1)^=f_+f_i\),但是有乙個特殊情況,即\(m(m-1)=f_\),即讓\(3\)號點到\(n\)號點都和\(1\)號點取值相等,這樣\(2\)號點和\(1\)不相同自然就不會和後面的點相同。
我們要求的是\(f_0\),我們發現\(f_0+f_1-(f_1+f_2)+f_2+f_3-....-f_+f_=f_0\),即我們配乙個\(-1\)的容斥係數即能求出\(f_0\)。
於是我們利用這個容斥就能斷環為鏈,所以我們來考慮更一般的鏈上問題,即\(a_i\)不同的情況。
有乙個顯然的暴力\(dp\),設\(dp_\)表示第\(i\)個點取值為\(j\)的方案數,\(s_i=\sum_^dp_\),轉移顯然有\(dp_=s_-dp_\)
由於我們的容斥本質上是使得最後連續的一段和\(1\)取值相等,這一段連續的取值受限於這一段中\(a_i\)的最小值,於是我們不妨選乙個\(a_i\)最小的點作為一號點,這樣每次\(dp\)的初值就不會改變,只需做一次\(dp\)即可。
考慮優化這個\(dp\)
當\(a_i>a_\)的時候,對於\(\forall j\in [1,a_]\)有\(dp_=s_-dp_\);當\(j>a_\)的時候,由於\(dp_=0\),所以對於\(j\in(a_,a_i]\)有\(dp_=s_\)
當\(a_的時候,對於\(\forall j\in [1,a_]\)有\(dp_=s_-dp_\);當\(j>a_i\)的時候,則有\(dp_=0\)
不難發現這幾個轉移我們只需要乙個能夠支援區間取反、區間加以及區間覆蓋的資料結構就能維護,於是直接使用線段樹來整體dp即可。
由於\(a_i\)比較大,所以得動態開點,複雜度是\(o(n\log a_i)\)只能有\(80pts\)
**
#include#define re register
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
#pragma gcc optimize(3)
#pragma gcc optimize("-fcse-skip-blocks")
inline int read()
const int mod=1e9+7;
const int m=7e7+5;
const int maxn=1e6+5;
int n,a[maxn],f[maxn],b[maxn],pos,mx,rt;
inline int qm(int x)
int l[m],r[m],gt[m],jt[m],sum[m],cnt;
bool ft[m];
inline void pushdown(int now,int lx,int ry)
if(ft[now])
if(jt[now])
}int gan(int now,int x,int y,int lx,int ry,int v)
pushdown(now,lx,ry);
int mid=lx+ry>>1;
if(x<=mid) l[now]=gan(l[now],x,y,lx,mid,v);
if(y>mid) r[now]=gan(r[now],x,y,mid+1,ry,v);
sum[now]=qm(sum[l[now]]+sum[r[now]]);
return now;
}int jia(int now,int x,int y,int lx,int ry,int v)
pushdown(now,lx,ry);
int mid=lx+ry>>1;
if(x<=mid) l[now]=jia(l[now],x,y,lx,mid,v);
if(y>mid) r[now]=jia(r[now],x,y,mid+1,ry,v);
sum[now]=qm(sum[l[now]]+sum[r[now]]);
return now;
}int qufan(int now,int x,int y,int lx,int ry)
pushdown(now,lx,ry);
int mid=lx+ry>>1;
if(x<=mid) l[now]=qufan(l[now],x,y,lx,mid);
if(y>mid) r[now]=qufan(r[now],x,y,mid+1,ry);
sum[now]=qm(sum[l[now]]+sum[r[now]]);
return now;
}int main()
for(re int i=1;i<=n;i++) mx=max(mx,a[i]);
f[1]=b[1];rt=gan(rt,1,b[1],1,mx,1);
for(re int i=2;i<=n;++i)
正解也就是容斥+dp,但是容斥方法好像不太一樣,就直接丟鏈跑了
正解
牛客提高訓練營5B 旅遊
題目 吉老師的題時過一年還是不會做 從 1 號點出發經過每條邊至少一次並且還要回到 1 號點,這跟尤拉迴路的條件非常像,但是尤拉迴路的實際上是 經過每一條邊恰好一次並且回到出發點 所以可以理解為將每一條邊拆成多條邊,使得總邊權和最小,並且圖中存在一條尤拉迴路 而一張圖存在尤拉迴路的條件是不存在度數為...
NOIP訓練營內部試題 分糖果
noip訓練營內部試題 分糖果 摘自 清北學堂noip訓練營試題t2 題目 分糖果 分糖果 candy time limit 1000ms memory limit 128mb 題目描述 總共有n顆糖果,有3個小朋友分別叫做l,y,k。每個小朋友想拿到至少k顆糖果,但這三個小朋友有乙個共同的特點 對...
牛客提高訓練營5A 同餘方程
題目 吉老師的題做不動啊 首先 l 1,r 1 l 2,r 2 並不是非常好做,我們考慮將其拆成字首資訊 設 solve n,m sum n sum m m i bigoplus j 於是我們的答案就變成了 solve r 1,r 2 solve l 1 1,r 2 solve r 1,l 2 1 ...