日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

NOIP模拟赛 四校联考 递推 + 分类讨论 + 树上期望

發布時間:2024/1/18 编程问答 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 NOIP模拟赛 四校联考 递推 + 分类讨论 + 树上期望 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

NOIP 模擬題
題目名稱兔子被子蚊子
源程序文件名rabbit.cpp quilt.cpp mosquito.cpp
輸入文件名rabbit.in quilt.in mosquito.in
輸出文件名rabbit.out quilt.out mosquito.out
每個測試點時限1s 1s 5s
內存限制512MB 512MB 512MB
測試點數目10 10 10
每個測試點分值10 10 10
是否打開O2 優化
否否否
在windows 下用lemon 進行測試.
AK 了不要婊出題人,沒AK 也不要婊出題人.

今天狀態非常不好… 本來說四校聯考發揮好點的, 事實上發現自己還是暴露了很多問題.

Rabbit

兔子(rabbit)
【題目描述】
做一只明媚的兔子…
兔子都比較喜歡蹦蹦跳跳.但是蹦蹦跳跳的時候如果一直往高處跳的話就太累了,如
果一直往低處跳的話就太無聊了.所以兔子希望跳的時候能夠往上跳一步,往下跳一步,
往上跳一步,往下跳一步….一共經過n個高度互不相同的位置(只要向上跳和向下跳相間
分布就可以了,第一步可以往上跳也可以往下跳).如果下一個位置的高度比前一個位置
高,就是往上跳,比前一個位置低,就是往下跳.
兔子今天又蹦蹦跳跳依次經過了n 個位置.現在它想知道經過的n 個位置的高度有
多少種不同的可能.
我們認為n 個位置的高度形成了1 到n 的一個排列,這個排列要么滿足奇數項的高
度比相鄰位置都大, 要么滿足偶數項的高度比相鄰位置都大.
n=1 時,有1 種可能,就是這1 個位置的高度為1
n=2 時,有2 種可能,可以是(1,2)或(2,1)
n=3 時,有4 種可能,(1,3,2) (2,3,1),(2,1,3),(3,1,2)
答案可能很大,只需要輸出答案對mod 取模的結果.
【輸入格式】
一行兩個整數n,mod
【輸出格式】
一行一個整數ans,表示所有可能的排列數目對mod 取模后的結果.
【樣例輸入1】
3 1000000007
【樣例輸出1】
4
【數據范圍】
第1,2 個測試點,5<=n<=10
第3,4 個測試點,11<=n<=13
第5,6,7 個測試點,14<=n<=16
第8,9 個測試點,100<=n<=200
第10 個測試點,n=2000
對于所有測試點,mod 在int 范圍內

題解

暴力的少見使用… 本來想的是f[i][j][0/1]表示第i個位置值為j, 是升是降的方案數. 后來發現無法知道當前j在之前出沒出現過, 所以就放棄打了個暴力. 算是這次唯一比較明智的選擇吧. 暴力就是dfs, 然后打表過前6個點, 如果比賽一開始寫快點的話能打出第7個點.

正解發現其實與原來的差不多, 用了一種很巧妙的理解方式避免了之前的方案也有j的情況. 首先奇和偶的方案數肯定是一樣的, 所以我們只需要考慮其中一種計算即可. 答案乘2即可. f[i][j]表示第i個數選j的方案數, 如果當前上升的話則可從f[i-1][j - 1, j-2…]等轉移過來, 下降反之. 現在考慮j在之前有沒有出現過. 假設j == i那么從之前之前的轉移過來肯定沒問題. 假設j < i, 那么我們只需要假想成前面i-1的排列大于等于j的全部都+1, 那么當前就也是一個合法的i的排列. 所以不會出現重復的情況. 這樣是n ^ 3的.
稍微改一下dp狀態, f[i][j]表示第i個數選1~j的方案數, 這樣f[i][j] = f[i][j-1] + f[i-1][i-j], 每次只考慮j這樣就是n^2的了, 相較于之前的就是一個前綴和優化. 為什么是f[i-1][i-j]?之前是升當前就是降, 狀態總是反的. 也可以說成把原來i-1的合法排列每個數取個反, 就可以迎合當前的j了.

#include<stdio.h> typedef long long dnt; const int maxn = 2005; int n, mod; dnt f[maxn][maxn]; int main(){freopen("rabbit.in", "r", stdin);freopen("rabbit.out", "w", stdout);scanf("%d%d", &n, &mod);f[1][1] = 1;for(int i = 2; i <= n; ++i)for(int j = 1; j <= i; ++j)f[i][j] = (f[i][j - 1] + f[i - 1][i - j]) % mod;printf("%I64d\n", (f[n][n] << 1) % mod); }

Quilt

被子(quilt)
【題目描述】
作為一只明媚的兔子,需要學會疊被子…
被子是方形的,上面有很多小寫字母.可以認為被子是一個n*m 的字符矩陣
被子能夠被疊起來,當且僅當每一行,每一列都是回文串.
兔子可以把同一條被子上任意兩個位置的字母交換位置,而且兔子不嫌麻煩,為了把
被子疊起來它愿意交換任意多次.但是兔子不能交換兩條不同的被子之間的字母.
現在兔子翻箱倒柜找出來了很多被子,請你幫兔子判斷每條被子能否被疊起來.
【輸入格式】
第一行一個Q,表示被子的條數
接下來描述Q 條被子.
描述每條被子時,第一行輸入兩個整數n,m 表示由n 行m 列組成
接下來n 行每行一個長度為m 的字符串.字符串中只含小寫字母.
【輸出格式】
Q 行,依次輸出對每條被子的判斷結果.如果可以疊起來,輸出一行“Yes”(不包括引
號),如果疊不起來,輸出一行“No”(不包括引號).
【樣例輸入】
5
3 4
aabb
aabb
aacc
2 2
aa
bb
5 1
t
weet
2 5
abxba
abyba
1 1
z
【樣例輸出】
Yes
No
Yes
No
Yes
【數據范圍】
第1,2 個測試點,n*m<=10
第3,4 個測試點,n=1
第5 個測試點,n=2
第6 個測試點,n,m 均為偶數
第7,8,9,10個測試點,捆綁測試,無特殊限制.只有通過這全部4個測試點才能拿到這4 個測試點的分數.
所有測試點,保證Q<=10,n,m<=200

題解

特判即可. 因為發現對于偶x偶的來說, 因為每行每列都要對稱, 那么每個字符出現的次數都應該是4的倍數.
對于奇x偶的情況, 只有奇中間那一行可以是%4 余 2的. 因為中間那一串自己成為一個回文串即可. 當然出現奇數次數的不行. 同時余2的個數必須要<列/2(如果列為偶的話, 其他反之).
對于奇x奇的情況, 允許一個奇數出現, 拿一個作為中間那一個. 其他余2的次數不能超過(n - 1 + m - 1) / 2.

#include<stdio.h> const int maxn = 205; int n, m, T; char s[maxn]; int cnt[30], mod[10]; inline bool check(){int num = n % 2 + m % 2;if(!num){if(mod[2] || mod[1]) return false;return true;}int lim;if(num == 1){if(mod[1]) return false;if(n & 1) lim = m / 2;else lim = n / 2;if(mod[2] <= lim) return true;else return false;}if(num == 2){if(mod[1] > 1 || !mod[1]) return false;if(mod[2] <= (n + m - 2) / 2) return true;else return false;} } int main(){freopen("quilt.in", "r", stdin);freopen("quilt.out", "w", stdout);scanf("%d", &T);while(T--){scanf("%d%d", &n, &m);for(int i = 0; i <= 4; ++i) mod[i] = 0;for(int i = 0; i <= 26; ++i) cnt[i] = 0;for(int i = 1; i <= n; ++i){scanf("%s", s + 1);for(int j = 1; j <= m; ++j)cnt[s[j] - 'a']++;}for(int i = 0; i <= 26; ++i){int mmod = cnt[i] % 4;if(mmod == 1) mod[1] ++; if(mmod == 2) mod[2] ++;if(mmod == 3) mod[2] ++, mod[1] ++;}if(check()) puts("Yes");else puts("No");}return 0; } /* 5 3 4 aabb aabb aacc 2 2 aa bb 5 1 t w e e t 2 5 abxba abyba 1 1 z */

蚊子(mosquito)
【題目描述】
作為一只明媚的兔子,要會疊被子,又得會打蚊子…
兔子住在兔子洞里.兔子洞可以看成是一棵無根樹,有n 個洞穴,有n-1 條通道連接
著n 個洞穴.
每天晚上,兔子會在1 號洞穴里縮成一團,睡一覺.同時,蚊子大軍出動,去欺負兔子.
因為蚊子人多勢眾,所以它們分兵m*(m-1)路.m 是整個兔子洞中只和一條通道相
鄰的洞穴數目.任意兩個這樣的洞穴a,b 之間(也就是任意兩個葉子節點之間)會有兩只
蚊子,一只從a 飛到b,一只從b 飛到a.它們都沿著a 到b 的最短路徑移動.蚊子每秒鐘可
以通過一條通道.所有蚊子都在0s 時突然出現在起點并開始移動.每只蚊子在到達終點
后的一瞬間都會突然消失.有些蚊子并不會經過兔子所在的1 號節點,它們起到的是恐嚇
作用.
又一次滿臉是包地醒來后,兔子忍無可忍了,于是它找到liu_runda 讓liu_runda 去
打蚊子…liu_runda不知所措,于是去某寶搞了一個滅蚊器…這個滅蚊器被放在1號節點.
每個時刻,它都會工作一次,把和滅蚊器距離小于等于d 范圍內的蚊子全部殺死.(d=0 時
只能控制1 號點一個位置)
遺憾的是,兔子洞尚未通電,兔子只能用愛發電. 因此,每個時刻滅蚊器只有p/q的概
率能夠正常工作.如果不能正常工作,那么蚊子將不受到任何影響.
滅蚊器無法影響出現之前和消失之后的蚊子.但在蚊子出現在起點和消失在終點的
那個時刻,如果滅蚊器正常工作且蚊子在作用范圍內,這只蚊子仍會被殺死.
兔子對liu_runda 的誠意表示懷疑…于是它讓liu_runda 算出滅蚊器在一晚上期望
能殺死多少蚊子.liu_runda 當然會算了,但是他想考考你.
因為兔子討厭小數,你需要輸出這個期望值模109+7 后的結果.即:如果期望值可以
表示成有理數a/b(a,b 為整數),你需要輸出a*b-1 mod 1000000007(109+7)的值.
(如果你算錯了,就會被liu_runda 拿去喂兔子,啊嗚~~)
【輸入格式】
第一行一個整數n,表示兔子洞中洞穴的個數.洞穴編號為1 到n 的整數.
接下來n-1 行,每行兩個整數u,v,表示u 和v 兩個洞穴之間有一條通道.
接下來一行三個整數d,p,q,表示滅蚊器的作用范圍是d,每個時刻工作的概率是
p/q.
【輸出格式】
一行一個整數ans,表示期望模109+7 的值.
【樣例輸入】
3
1 2
1 3
1 1 2
【樣例輸出】
750000007
【樣例解釋】
共有2 只蚊子,一只從2 飛到3,一只從3 飛到2.滅蚊器的作用范圍是1,那么
三個點都在作用范圍內,每個蚊子會有三個時刻在作用范圍內,那么每只蚊子生還的概率
都是1/8,經過計算,我們期望能夠打死7/4 只蚊子,說明liu_runda 提供的滅蚊器是比
較靠譜的.我們輸出7*4-1mod1000000007 的值750000007.
【數據范圍】
記m 為葉子節點的個數.
對于第1 個測試點,n=300
對于第2,3 個測試點,n=3000
對于第4 個測試點,d=0,n=100000
對于第5 個測試點,p/q=1,n=100000
對于第6,7 個測試點n=5000000,m<=500
對于第8,9,10 個測試點,n=5000000
對于所有測點,m < n<=5000000,0<=d<=n,1<=p<=q<=109+7 保證1 號節點至少和兩條通道相連.

題解

感覺是比較naive的期望, noip難度. 但是還是寫錯了. 存活的蚊子要好算得多, 直接最后用總的蚊子 - 期望存活的蚊子就是題目所求.
我們會發現我們只用考慮lca的貢獻. 對于一個葉子節點到另一個葉子節點, 我們可以看成一個葉子節點到lca的, 和另一個到lca的, 我們稱之為半路徑. 這樣相乘就是合法的路徑, 再來算期望活著的蚊子. 我們對于每一節點用f數組來存所有這樣的半路徑, 那么對于u的兒子v. v到u其他子樹的所有路徑貢獻就是(f[u] - f[v]) * f[v], 這就映射了所有路徑(在dep[u]是否 小于d是要特判一下f[v]的貢獻), 也就算出了所有期望存活的蚊子.
注意那個分數可以一開始就轉成分子乘分母的逆元來處理.

#include<stdio.h> const int mod = 1e9 + 7; const int maxn = 5e6 + 5; typedef long long dnt; int n, num, d, pp, qq; int h[maxn], dep[maxn], siz[maxn]; dnt f[maxn], ans, p; struct edge{ int nxt, v;}e[maxn * 2]; inline int read(){register int x = 0;register char ch = getchar();while(ch < '0' || ch > '9') ch = getchar();while(ch >= '0' && ch <= '9') x = (x << 3) + (x << 1) + ch - '0', ch = getchar();return x; } inline void add(int u, int v){e[++num].v = v, e[num].nxt = h[u], h[u] = num;e[++num].v = u, e[num].nxt = h[v], h[v] = num; } inline dnt mpow(dnt a, dnt b){dnt ret = 1;while(b){if(b & 1) ret = ret * a % mod;a = a * a % mod, b >>= 1;}return ret; } void dfs(int u, int fa){for(int i = h[u]; i; i = e[i].nxt){int v = e[i].v;if(v == fa) continue;dep[v] = dep[u] + 1;dfs(v, u);siz[u] += siz[v];f[u] = (f[u] + f[v] * p) % mod;}if(!siz[u]){siz[u] = 1;if(dep[u] <= d) f[u] = p;else f[u] = 1;return;}if(dep[u] > d) f[u] = siz[u];dnt delta = 0;for(int i = h[u]; i; i = e[i].nxt){int v = e[i].v;if(v == fa) continue;if(dep[u] <= d) delta = f[u] - f[v] * p;else delta = f[u] - f[v];delta = (delta % mod + mod) % mod;ans = (ans + delta * f[v] % mod) % mod;} } int main(){freopen("mosquito.in", "r", stdin);freopen("mosquito.out", "w", stdout);n = read();int u, v;for(int i = 1; i < n; ++i){u = read(), v = read();add(u, v);}d = read(), pp = read(), qq = read();p = 1ll * (qq - pp) * mpow(qq, mod - 2) % mod;dfs(1, 1);ans = (1ll * siz[1] * (siz[1] - 1) % mod - ans + mod) % mod;printf("%I64d\n", ans);return 0; }

總結

以上是生活随笔為你收集整理的NOIP模拟赛 四校联考 递推 + 分类讨论 + 树上期望的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。