惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
A
About on SuperTechFans
IT之家
IT之家
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
Blog — PlanetScale
Blog — PlanetScale
aimingoo的专栏
aimingoo的专栏
云风的 BLOG
云风的 BLOG
The GitHub Blog
The GitHub Blog
Vercel News
Vercel News
G
Google Developers Blog
J
Java Code Geeks
宝玉的分享
宝玉的分享
T
Tailwind CSS Blog
Cloudbric
Cloudbric
L
LINUX DO - 最新话题
MyScale Blog
MyScale Blog
H
Heimdal Security Blog
PCI Perspectives
PCI Perspectives
Attack and Defense Labs
Attack and Defense Labs
S
Security @ Cisco Blogs
Latest news
Latest news
I
Intezer
L
Lohrmann on Cybersecurity
C
CXSECURITY Database RSS Feed - CXSecurity.com
月光博客
月光博客
T
Threatpost
博客园 - 【当耐特】
S
Schneier on Security
P
Privacy International News Feed
G
GRAHAM CLULEY
T
Tenable Blog
AWS News Blog
AWS News Blog
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
雷峰网
雷峰网
博客园 - Franky
Engineering at Meta
Engineering at Meta
美团技术团队
S
Secure Thoughts
T
Troy Hunt's Blog
Microsoft Security Blog
Microsoft Security Blog
SecWiki News
SecWiki News
V
Visual Studio Blog
人人都是产品经理
人人都是产品经理
Application and Cybersecurity Blog
Application and Cybersecurity Blog
Cisco Talos Blog
Cisco Talos Blog
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
Martin Fowler
Martin Fowler
Webroot Blog
Webroot Blog
Google DeepMind News
Google DeepMind News
H
Hackread – Cybersecurity News, Data Breaches, AI and More

Louis C Deng's Blog

CS231n Lecture Note: Generative Models CS231n Lecture Note: Self-Supervised Learning CS231n Lecture Note: Large Scale Distributed Training 自動微分 | DIY 實現自己的 PyTorch From RNNs to Transformers CS231n Lecture Note VII: Recurrent Neural Networks Uncovering Batch & Layer Normalization CS231n Lecture Note VI: CNN Architectures and Training CS231n Lecture Note V: Convolution Neural Networks Basics Demystifying Softmax Loss: A Step-by-Step Derivation for Linear Classifiers Backpropagation: A Vector Calculus Perspective CS231n Lecture Note IV: Neural Networks and Backpropagation CS231n Lecture Note III: Optimization CS231n Lecture Note II: Linear Classifiers CS231n Lecture Note I: Image Classification CSAPP Cache Lab II: Optimizing Matrix Transposition CSAPP Cache Lab I: Let's simulate a cache memory! CS188 Search Lecture Notes III CS188 Search Lecture Notes II How to Use TouchID for Sudo Commands on macOS CS188 Search Lecture Notes I RECAP2025: 留白 CSAPP Bomb Lab 解析 x64 暫存器速查表 CSAPP Data Lab 解析 矩陣的 Modified Gram Schmidt 方法 聊一聊位掩碼(Bit Mask) 整數溢位與未定義行為 快速排序 幾種劃分方法討論 等待 記夢(DeepSeek 輔助創作) 午夜飛行 橋樑 黎明 或 2012 RECAP2024: 水檻臥聽雨 太陽、潮落 RECAP2023: 泡沫 題解 P1622 釋放囚犯 殘陽似火 再會 飢餓藝術家 卡夫卡 Python 中的 zip() 和 enumerate() 泡沫 “救救孩子……”——談魯迅和《狂人日記》 想念 淺灘 蟬 · 夏 微風 觀星 浮塵 復活 【摘錄 | 轉載】普魯斯特 《追憶似水年華》第一卷 《在斯萬家那邊》(一) Time - Pink Floyd - The Dark Side of the Moon 【轉載】靜夜思變調 高樓 幻夢 冰 RECAP2022: 流星雨 清夜 割點 Tarjan 演算法 P3147 USACO16OPEN 262144 P 題解 P3354 Riv 河流 題解 馬拉車演算法 夜雨 層霧 從愚人節玩笑到真的玩笑(bushi): 淺談 lsnotes I made my own Hexo theme 題解 紀念品分組 題解 導彈攔截 如何高效使用搜尋引擎 用 GitHub Actions 格式化 C/C++ 程式碼 四季的天空 洛谷 7 月月賽 Div.2 總結 題解 最近公共祖先 (LCA) 用簡單的物理方法證明牛頓萊布尼茨公式 簡評榮耀手環6 海上生明月,天涯共此時。 我為什麼重新拿出了 iPod Swift 中的 SharedPreferance —— UserDefaults 凝視那一輪明月 用 GitHub Actions 部署 Hexo 部落格 遲來的日誌 - WWDC 2020 獎學金 vcpkg - 方便的 C/C++ 庫管理器 vimrc 配置指南 NextCloud - DIY NAS 解決方案 sudo shutdown -r now sudo shutdown -r now
題解 P5888 傳球遊戲
Louis C Deng · 2023-10-17 · via Louis C Deng's Blog

題目連結:P5888

題面

題目背景

羊城有善蹴鞠者。會足協之杯,於校園之東北角,施兩球場,蹴鞠者站球場中,nn 人,一球,二門,三裁判而已。觀眾團坐。少傾,但聞球場中哨聲一響,滿坐寂然,無敢譁者。

當是時,傳球聲,微微風聲,隊員疾跑聲,教練呼喊聲,拉拉隊助威聲,一時齊發,眾妙畢備。滿場觀眾無不伸頸,側目,微笑,默嘆,以為妙絕。

未幾,我球員施一長傳,彼球員截之,望我龍門衝來。

但見守門員 oql 立於門,若有所思——

題目描述

原來他在想這麼一個問題:

場上的 nn 個球員圍成一圈,編號從 11nn ,剛開始球在 11 號球員手中。一共 mm 次傳球,每次傳球必須傳給一個人,但不能傳到自己手中。求第 mm 次傳球以後傳回 11 號球員的方案數。

但他覺得這個問題太簡單了,於是加了 kk 條限制,每條限制形如 a,ba,b,表示 aa 號球員不能將球傳給 bb 號球員。

為了使得 oql 的注意力轉移回球場上,你需要在最短的時間內告訴他這個方案數是多少。

你只需要告訴他答案對 998244353998244353 取模後的結果。

輸入格式

輸入資料包括 k+1k+1 行:

第一行三個整數 n,m,kn,m,k,分表代表球員數,傳球次數,限制條數。

接下來 kk 行,每行兩個整數 ai,bia_i,b_i,表示 aia_i 號球員不能將球傳給 bib_i 號球員。

資料保證不會出現不同的 i,ji,j 使得 ai=aja_i=a_jbi=bjb_i=b_j

輸出格式

輸出一個整數,表示 mm 輪後傳回 11 號球員的合法方案數對 998244353998244353 取模後的結果。

樣例 #1

樣例輸入 #1

1
2 1 0

樣例輸出 #1

1
0

樣例 #2

樣例輸入 #2

1
3 3 0

樣例輸出 #2

1
2

樣例 #3

樣例輸入 #3

1
2
3
4
5
6
7 13 5
1 3
4 5
5 4
6 1
2 2

樣例輸出 #3

1
443723615

提示

對於 10%10\% 的資料,k=0k=0

對於另外 15%15\% 的資料,n≤500n\leq 500

對於另外 20%20\% 的資料,n≤5×104n\leq 5\times 10^4

對於另外 20%20\% 的資料,k≤300k\leq 300

對於 100%100\% 的資料,1≤n≤1091\leq n\leq 10^90≤m≤2000\leq m\leq 2000≤k≤min⁡(n×(n−1),5×104)0\leq k \leq \min(n\times(n-1),5\times 10^4)1≤ai,bi≤n1\leq a_i,b_i\leq n不保證 ai,bia_i,b_i 不相等

思路

首先看到題目,如果沒有k限制,顯然是DP。

設計狀態 f[i][j] 表示第i局遊戲傳到j的方法數,顯然滿足 DP 的要求(無後效性、最優子結構等)。

得到狀態轉移方程:f[i][j] = sum of f[i-1][k]。其中k表示能夠傳到j的所有人。

但每次遍歷k還是太麻煩,題目中顯然能夠傳到j的人數大於受限人數。所以我們採用做差的方法,使用f[i][j] = sum of f[i-1][k] - f[i-1][m],此時k表示所有人,m表示不能傳球的人。所有人的方法數和可以使用一個變數記錄。

但是我們發現,題目中n的範圍到1e9,顯然無法開這麼大的陣列去算。

思考發現,題中限制數很少,只有5e4,最壞情況(限制中,ab均不同),存在約束的人數也只有1e5,剩下的是毫無限制的“自由人”,因此可以簡化問題,成為“自由人”、自己(即1)和“限制人”的傳球遊戲。

“自由人”可以“自傳球”,需要注意。而且這樣做之後,編號會混亂,我們需要建立一個map重新建立編號。

還有什麼最佳化方法?

滾動陣列,可以將f壓縮!

程式碼實現

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
#include <iostream>
#include <cstring>
#include <algorithm>
#include <queue>
#include <map>

using namespace std;

#define MOD 998244353

struct Node{
int next, to;
}NDS[100010];

int cnt = 0;
int head[100010];

void add(int a, int b){
NDS[cnt].to = b;
NDS[cnt].next = head[a];
head[a] = cnt++;
}

vector<int> P;
int DP[2][100010];

map<int, int> Dict;

int main() {
memset(head,-1,sizeof(head));
int n,m,k;
cin >> n >> m >> k;
for(int i = 1; i<=k; i++){
int a,b;
cin >> a >> b;

int ida, idb;
if(!(ida = Dict[a])) P.push_back(Dict[a] = ida = Dict.size());
if(!(idb = Dict[b])) P.push_back(Dict[b] = idb = Dict.size());
if(ida != idb) add(idb,ida);
}

if (!Dict[1]) P.push_back(Dict[1] = Dict.size());
int Nc = Dict.size();
int Fc = n - Nc, idf = Dict.size()+1;

int sum = 1, sum2 = 0;
DP[0][Dict[1]] = 1;
for(int i = 1; i<=m; i++){
int cur = i&1;
int prev = 1-cur;
sum2 = sum;
sum = 0;
for(int j : P){
DP[cur][j] = ((sum2 - DP[prev][j])%MOD + MOD)%MOD;
for(int x = head[j]; x!=-1; x=NDS[x].next){
int y = NDS[x].to;
if(y==j) continue;
DP[cur][j] = ((DP[cur][j] - DP[prev][y])%MOD + MOD) % MOD;
}
sum += DP[cur][j];
sum %= MOD;
}
DP[cur][idf] = (1LL * sum2 * Fc % MOD - 1LL * DP[prev][idf] % MOD)%MOD;
sum = (sum % MOD + DP[cur][idf] % MOD) % MOD;
}
cout << DP[m&1][Dict[1]]%MOD << endl;
return 0;
}

更多注意事項

這道題我在取模的時候調了很久 -> “C++負數取模還是負數,應該將其變成正數”

小結

本題是一個動態規劃問題,難點在於模型的建立。