[ABC310F] Make 10 Again
分母是 \(\prod a_i\),只需求分子。
首先要發現投出了 \(10\) 以上的點數是無用的,所以只需考慮 \(10\) 以內的。
思考如何計數,發現轉移依賴於前面的點數和的方案數,而且 \(10\) 很小,考慮狀壓 DP,設 \(f_{i,s}\) 表示前 \(i\) 個骰子,狀態為 \(s\) 的方案數,轉移不表。
\(s\leq M=2^{11}\),所以時間複雜度 \(\mathcal{O}(nM10^2)\)。
[ARC174E] Existence Counting
怎麼就沒想到呢??一直想著直接計數,比較困難,正難則反,轉化為:排列數 \(-\) 沒出現 \(x\) 的排列數 \(-\) 字典序大於 \(P\) 的方案數 \(+\) 既沒出現 \(x\) 字典序還大於 \(P\) 的方案數。轉化後就比較基礎了。
[ARC173C] Not Median
感覺還是不夠。
直覺告訴我們,答案大多數都很小。
注意到答案很大的地方周圍應該長這樣 -+-+-+0-+-+-+
,這告訴我們只需找到兩個相鄰的值又同時在 \(p_i\) 一側的就好了。
每個點都往左右掃,複雜度看似 \(\mathcal{O}(n^2)\),但是其實在 \(i\) 和 \(x_1,x_2\) 之間的所有數答案一定是 \(3\),這意味著每個數只會被掃一遍。所以時間複雜度 \(\mathcal{O}(n)\)。
[ABC281G] Farthest City
將所有點按最短路分層,每層的節點只能和相鄰層還有層內的節點連邊。設 \(f_{i,j}\) 表示用了 \(i\) 個點,最後一層有 \(j\) 個點的方案。轉移:
CF1476F Lanterns
典題,覆蓋問題可以將狀態設計成 \(f_i\) 表示前 \(i\) 盞燈能覆蓋的最長字首。
轉移分三類:
- 前面不能覆蓋到 \(i\),直接不管 \(i\),\(f_i=f_{i-1}\)。
- 前面能覆蓋到 \(i\),\(f_i=\max(f_{i-1},i+p_i)\)。
- 將 \(i\) 向左,找到一個 \(f_j\ge i-p_i\) 最小的 \(j\),然後 \(j+1\sim i-1\) 全部向右,\(f_i=\max\{k+p_k\}\)。
不知道為什麼想這麼久,明明這麼簡單。
[ARC154C] Roller
有 ARC182B 作為基礎這題很容易想到做法,將相同的合併成一塊,只需判斷是否存在一個斷點使得 \(a\) 是 \(b\) 的子序列。
但是還需要空餘的位置,可以是 \(a\) 中 \(b\) 沒出現的,可以是 \(b\) 中相鄰的,也可以是 \(a\) 中相鄰的。若沒有空餘位置則必須 \(a,b\) 完全相等。
細節一直寫掛,陣列還開小了。
P3214 [HNOI2011] 卡農
想不出來。
設 \(f_i\) 表示選了 \(i\) 個子集且滿足條件的方案。考慮容斥,為了滿足和前面的 \(i-1\) 個子集加在一起全是偶數,前面每種選法都唯一確定一種子集,方案數為 \(A_{2^n-1}^{i-1}\)。
再減去 \(i\) 為空的情況,方案數為 \(f_{i-1}\)(去掉 \(i\) 之後能滿足條件)。
再減去 \(i\) 和前面相同的方案。去掉 \(i\) 和 \(j\) 後也能滿足條件,\(j\) 有 \(i-1\) 種取值,子集 \(i\) 有 \(2^n-1-(i-2)\) 種取法,方案數為 \(f_{i-2}\times (i-1)\times (2^n+1-i)\)。
最後輸出 \(\dfrac{f_m}{m!}\)。
P3577 [POI2014] TUR-Tourism
在無向圖搜尋樹上 DP,沒見過。
由題得樹的深度不超過 \(10\),這啟發我們用樹上狀壓 DP(還是沒見過)。
一個重要的性質:無向圖 DFS 樹上的非樹邊一定是回邊,不存在橫叉邊。所以我們可以狀壓父親的狀態。
DP 過程較為複雜,不寫。
P6381 『MdOI R2』Odyssey
透過質因數分解我們很容易判斷是否能構成完美數對,但是資訊在邊上我們很難直接 DP。
但我們發現如果用雜湊去表示每一條邊,那麼能與它配對的邊的雜湊值也是確定的。這啟發我們設 \(f_{i,h_i}\) 表示以 \(i\) 為終點,最後一條邊雜湊值是 \(h_i\) 的答案,時間複雜度 \(\mathcal{O}(n\log n\times 11)\)。
P8860 動態圖連通性
很牛逼。
首先肯定要離線,然後多次詢問的邊只有第一次有用。
記邊被詢問的時間為 \(d_i\),沒詢問的視作 \(d_i=Q+1\)。將 \(d_i\) 作為邊的邊權,那麼就是要找一條路徑,使得將路徑上的邊的權值從大到小排序,字典序最小。
類似 「The classic problem」一樣用主席樹維護最短路。
CF464D World of Darkraft
需要注意到 \(k\) 種裝備地位相同,所以只需計算一種裝備最後乘 \(k\)。設 \(f_{i,j}\) 表示還剩 \(i\) 個怪獸,裝備等級為 \(j\) 的期望。轉移不表。
[ABC370F] Cake Division
不會倍增的菜鳥了屬於是。
二分答案,記 \(f_i\) 為從 \(i\) 開始的一個連續段的結尾 \(+1\)(即下一個連續段的開頭),那麼就是從 \(i\) 開始跳 \(k\) 次 \(f\) 看終點是否滿足條件。這顯然倍增。
P7603 [THUPC2021] 鬼街
減半警報器。
一次靈異事件的發生可以暴力給所有質因子 \(+y\),因為質因子個數很少。問題是什麼時候統計答案。
對於一個 \((x,y)\) 的監控,記加入時其質因子已經發生了 \(s\) 次靈異事件,響警報的條件是 \(\sum\limits _{p}cnt_p\ge y+s\)。轉化成 \(\sum \Delta cnt_p\ge y\)。那肯定至少有一個 \(p\) 滿足 \(\Delta cnt_p\ge \lceil\frac{y}{d_x} \rceil\),我們將其設為閾值,當一個房間裡有監控達到閾值時我們就拿出來 check 一下,這可以用優先佇列實現。
如果 check 失敗,我們讓閾值變成 \(\lceil\frac{y-\sum\Delta cnt_p}{d_x} \rceil\),然後重新加入優先佇列。不難發現, 每次閾值至少減少 \(\dfrac{1}{d_x}\),所以時間複雜度 \(\mathcal{O}(m\times d_V\log V\log n)\)。
[ARC171C] Swap on Tree
每棵子樹最多 \(siz+1\) 種取值,且新的數是什麼不重要。設 \(f_{x,t,0/1}\) 表示以 \(x\) 為根的子樹,與 \(x\) 相連的邊斷了幾條邊,和父親的邊是否斷了的方案數。
\(f'_{x,t,0}\leftarrow f_{x,t-1,0}\times f_{y,s,1}\times t+f_{x,t,0}\times f_{y,s,0}\)
\(f'_{x,t,1}\leftarrow f_{x,t-1,1}\times f_{y,s,1}\times t+f_{x,t,1}\times f_{y,s,0}\)
初始化 \(f_{x,0,0}=1\),\(f_{x,1,1}=[x\ne 1]\)。
P6383 『MdOI R2』Resurrection
其實就是聯通塊的根之間連邊。
容易想到設 \(f_{x,i}\) 表示 \(x\) 上面還有 \(i\) 個點可供選擇的方案數,但是不會做轉移。
因為 \(x\) 的選擇會使得 \(i\) 的限制發生變化,而且 \(x\) 與兒子的誰先與父親切斷對轉移也有影響。平常的樹形 DP 依賴於兒子的狀態,而這裡對父親也提出要求。
考慮分析圖的性質,然後就發現兒子連的邊一定不會與父親連的邊交叉,要不連父親,要不連父親連的點的上面。分析出這點,然後就可以列舉父親連的點進行轉移了。
P6009 [USACO20JAN] Non-Decreasing Subsequences P
靜態區間查詢,考慮貓樹分治。
如何合併兩個前字尾資訊,記 \(g_{i,j}\) 表示 \([i,mid]\) 裡以 \(j\) 結尾的不下降子序列數量。將值域放到狀態裡即可合併。
P9716 [EC Final 2022] Coloring
先把環找出來,然後對於環上的每個點,以它為根對子樹進行 DP。
顯然每次覆蓋不會完全覆蓋上一次,那麼最後的覆蓋次數肯定是從子樹的上到下減小的,所以設 \(f_{x,i}\) 表示 \(x\) 覆蓋了 \(i\) 次的答案,轉移不表。
若 \(s\) 不在環上,則答案為 \(\max(f_{s,1},f_{s,2})\)。
否則,我們對這個環進行考慮,手玩一下發現,最後以 \(s\) 為開頭按照邊的方向形成的節點序列的操作次數單調不升,且極差 \(\leq 2\),所以列舉最小值然後 DP。
有一些細節。
GJOI 9.11 T2
對於 \(01\) 串 \(x\),一次操作指將其一個子串反轉(\(0\rightarrow 1\),\(1\rightarrow 0\)),定義 \(x\) 的權值為使得 \(x\) 滿足任意一對相鄰字元均不相同。
\(q\) 個詢問,每次詢問子串 \(s[l:r]\) 的所有非空子序列之和。
\(n,q\leq 5\times 10^6\)。
記 \(w=\sum\limits_{i=1}^{n-1}[s_i\ne s_{i+1}]\),則 \(s\) 的權值為 \(\left\lceil\dfrac{w}{2}\right\rceil\)。這樣可以設計出 \(\mathcal{O}(n^2q)\) 的DP。使用貓樹最佳化可以做到 \(\mathcal{O}(n\log n+q)\)。
但是題目要求線性,上述的 DP 沒有最佳化前途。
考慮將 \(\lceil\frac{w}{2}\rceil\) 拆成 \(\frac{1}{2}(w+[2\not\mid w])\),只需計算所有子序列 \(w\) 的和還有 \(w\) 為奇數的子序列個數。
-
先計算前者,對於 \(l\le i<j\le r\) 且 \(s_i=s_j\) 的字元,只有當它們同時出現在某個子序列且相鄰才有貢獻,則總貢獻為
\[\sum\limits_{l\le i<j\le r,s_i=s_j}2^{r-l+i-j}\\=2^{r-l}\left(\sum\limits_{1\le i<j\leq r,s_i=s_j}2^{i-j}-\sum\limits_{1\le i<l,l\le j\le r,s_i=s_j}2^{i-j}-\sum\limits_{1\le i<j<l,s_i=s_j}{2^{i-j}} \right) \] -
再計算後者,有結論一個子序列 \(w\) 的奇偶性與等於子序列長度和 \([s_{st}=s_{ed}]\) 之和的奇偶性。
對於 \(st\ge ed-1\),特判。
對於 \(st< ed-1\),若 \(st,ed\) 固定,則長度為奇數的子序列和偶數相等,為 \(2^{ed-st-2}\)。
則總貢獻為
\(\sum\limits_{l\le i<r}[s_i=s_{i+1}]+\sum\limits_{l\le i<j-1\le r}2^{j-i-2}\\=\sum\limits_{l\le i<r}[s_i=s_{i+1}]+\sum\limits_{2\le i\le r-l}2^{i-2}(r-l-i+1)\)
時間複雜度 \(\mathcal{O}(n+q)\)。
GJOI 9.10 T2
#include<bits/stdc++.h>
#define LL long long
using namespace std;
const int N=5e6+10,MOD=1e9+7;
int n,Q,opt,al,bl,ar,br,l,r;
LL res;
int pw[N],ipw[N],pre[N],s1[N],s2[N];
int A[N][2][2],B[N];
char s[N];
void addm(int &x,int y){(x+=y)%=MOD;if(x<0)x+=MOD;}
int ksm(int x,int y)
{
int res=1;
while(y)
{
if(y&1) res=1LL*res*x%MOD;
x=1LL*x*x%MOD;
y>>=1;
}
return res;
}
void init()
{
pw[0]=ipw[0]=1;
for(int i=1; i<=n; i++)
pw[i]=1LL*pw[i-1]*2%MOD;
ipw[n]=ksm(pw[n],MOD-2);
for(int i=n-1; i>=1; i--)
ipw[i]=1LL*ipw[i+1]*2%MOD;
for(int i=1; i<=n; i++)
{
if(i>1) pre[i]=pre[i-1]+(s[i-1]==s[i]);
s1[i]=(s1[i-1]+pw[i-1])%MOD;
s2[i]=(s2[i-1]+1LL*pw[i-1]*(n-i)%MOD)%MOD;
bool cur=(s[i]=='1');
B[i]=B[i-1];
addm(B[i],1LL*ipw[i]*A[i-1][cur][0]%MOD);
A[i][0][0]=A[i-1][0][0];
A[i][0][1]=A[i-1][0][1];
A[i][1][0]=A[i-1][1][0];
A[i][1][1]=A[i-1][1][1];
addm(A[i][cur][0],pw[i]);
addm(A[i][cur][1],ipw[i]);
}
}
int main()
{
freopen("alternate.in","r",stdin);
freopen("alternate.out","w",stdout);
scanf("%d%d%d%s",&n,&Q,&opt,s+1);
if(opt) scanf("%d%d%d%d%d%d",&al,&bl,&ar,&br,&l,&r);
init();
for(int i=1; i<=Q; i++)
{
if(opt)
{
int tf=(1LL*al*l%n+bl)%n+1,tg=(1LL*ar*r%n+br)%n+1;
if(tf>tg) swap(tf,tg);
l=tf; r=tg;
}
else scanf("%d%d",&l,&r);
int ans=0;
addm(ans,B[r]); addm(ans,-B[l-1]);
addm(ans,-1LL*(A[r][0][1]-A[l-1][0][1]+MOD)%MOD*A[l-1][0][0]%MOD);
addm(ans,-1LL*(A[r][1][1]-A[l-1][1][1]+MOD)%MOD*A[l-1][1][0]%MOD);
ans=1LL*ans*pw[r-l]%MOD;
addm(ans,pre[r]-pre[l]);
addm(ans,s2[r-l-1]); addm(ans,-1LL*s1[r-l-1]*(n-r+l)%MOD);
ans=1LL*ans*ipw[1]%MOD;
if(opt) res^=(LL)(ans+i*23);
else printf("%d\n",ans);
}
if(opt) printf("%lld\n",res);
return 0;
}