2020 08 18 集訓題目題解

2022-05-01 19:48:10 字數 3155 閱讀 4331

講數字dp,然後發現自己學暴了,這裡挑幾道有意思的題目記錄一下,以免將來死得太慘。

題目傳送門

定義 windy 數為滿足相鄰兩位差值 \(\le 2\) 的數,給出 \(l,r\) ,求出 \([l,r]\) 內有多少 windy 數。

\(l,r\le 2\times 10^9\)

我™ 這樣乙個板子題調了乙個小時,果然是我自己菜爆了。。。

我們可以設 \(dp[i][x]\) 表示確定了前 \(i\) 位並且第 \(i\) 位為 \(x\) 時的合法方案數,然後直接記憶化搜尋就好了。下面是一些數字 dp 的細節

原因就是這兩種情況會限制後面幾位的選擇。

#include using namespace std;

#define int register int

#define maxn

template inline void read (t &t)while (c >= '0' && c <= '9') t *= f;}

template inline void read (t &t,args&... args)

template inline void write (t x)if (x > 9) write (x / 10);putchar (x % 10 + '0');}

int len,nnum[11],dp[11][10];

int abs (int x)

int dfs (bool up,bool zero,int now,int x)

int calc (int n)

signed main()

題目傳送門

定義乙個數字與 \(7\) 有關當且僅當一下幾種情況:

給出 \([l,r]\) ,求出該區間內與 \(7\) 無關的數字的平方和。

\(l\le r\le 10^\),答案對 \(10^9+7\) 取模。

顯然我們沒有辦法直接搞了。但是我們發現假設當前位為 \(x\) ,後面為 \(y\) ,那麼答案就是 \((x+y)^2=x^2+2xy+y^2\) ,然後我們發現 \(\text =x^2\times \sum+ 2x\times y+\sum y^2\) ,然後我們直接維護合法方案數、合法方案的數字和、合法數字的平方和即可。

#include using namespace std;

#define int register int

#define mod 1000000007

#define int long long

template inline void read (t &t)while (c >= '0' && c <= '9') t *= f;}

template inline void read (t &t,args&... args)

template inline void write (t x)if (x > 9) write (x / 10);putchar (x % 10 + '0');}

int len,pw[19],nnum[19];

int mul (int a,int b)void mul (int &a,int b)

int dec (int a,int b)void dec (int &a,int b)

int add (int a,int b)void add (int &a,int b)

struct node

}dp[19][7][7];

node dfs (bool lim,int now,int sum1,int sum2)

if (!lim && dp[now][sum1][sum2].exi) return dp[now][sum1][sum2];

int up = lim ? nnum[now] : 9;node res;res.clear();

for (int i = 0;i <= up;++ i)

if (!lim) dp[now][sum1][sum2] = res,dp[now][sum1][sum2].exi = 1;

return res;

}int calc (int n)

signed main()

return 0;

}

題目傳送門

給出 \(l,r,k\) ,將 \([l,r]\) 劃分成某些段,使得每一段上面的編號的每位數字之和不小於 \(k\) 並且盡可能小。求出分成的段數。

\(l\le r\le 10^,k\le 1000\)

為了更好幫助理解題意,比如 \(l=40,k=11\) ,那麼 \(40,41,42\) 就會被劃分成一段,因為 \(4+0+4+1+4+2\ge 11\) 而且 \(4+0+4+1<11\)。

私認為是很巧妙的一道題。我們可以考慮設 \(dp[i][s1][s2]\) 表示考慮第 \(i\) 位當前編號,\(s1\) 為當前編號產生的每位數字之和,\(s2\) 表示已經劃分出來的貢獻。然後我們就可以進行合併,具體見**。

#include using namespace std;

#define int register int

#define int long long

template inline void read (t &t)while (c >= '0' && c <= '9') t *= f;}

template inline void read (t &t,args&... args)

template inline void write (t x)if (x > 9) write (x / 10);putchar (x % 10 + '0');}

int l,r,k,tmp,lnum[19],rnum[19];

struct node

node (int _a,int _b,bool _exi)

}dp[20][185][1010];

void merge (node &x,node y)

node dfs (bool lim1,bool lim2,int now,int sum,int rem)

else

if (!lim1 && !lim2) dp[now][sum][rem] = ans,dp[now][sum][rem].exi = 1;

return ans;

}signed main()

2020 08 05 集訓題目題解

題目傳送門 給出乙個長度為 n 的數列 a 有 m 次操作,每次操作分別為以下兩種 n,m le 5 times 10 4 其實我們可以發現乙個事情,最後 c bmod varphi 1 varphi 1 bmod varphi p varphi p 然後我們就發現到了一定程度之後再加上 c 都不會...

2022 02 06 集訓題解

不難注意到的是,我們假設 f i 為 i 之前 le a i 的值的個數,那麼我們需要滿足 sum i f i sum i min i,a i 又因為我們可以知道 f i le min i,a i 所以我們對於每乙個 i 都有 f i min i,a i 考慮如何構造這樣的 a 可以發現,我們選了乙...

2022 04 04 集訓題解

小 w 的手上有一顆 n 個節點的二叉搜尋樹,裡面有從 1 到 n 這 n 個數字。二叉搜尋樹即為中序遍歷恰好為 1 到 n 的二叉樹 現在你想知道這棵樹的形態。但是小 w 不會直接告訴你,只允許你詢問以某個點為根的子樹是否恰好包含 l,r 中的所有點。你需要在 2 times n 次查詢之內得到整...