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

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

2021百度之星程序设计大赛-初赛一部分题目总结

發(fā)布時(shí)間:2023/12/9 编程问答 34 豆豆
生活随笔 收集整理的這篇文章主要介紹了 2021百度之星程序设计大赛-初赛一部分题目总结 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

部分題目

  • 1001迷失
    • 鄰接矩陣k次方的結(jié)論
    • 拆點(diǎn)法
  • 1003鴿子
  • 1004萌新
  • 1006毒瘤數(shù)據(jù)結(jié)構(gòu)題
  • 1008獵人殺

1001迷失

  • 題目意思是要從111號(hào)島嶼經(jīng)過(guò)kkk條路徑到達(dá)nnn號(hào)島嶼的概率,里面提出了一個(gè)附魔橋和普通橋的概念,經(jīng)過(guò)附魔橋身上如果有附魔則附魔消失,如果沒(méi)有附魔則被標(biāo)記;到達(dá)nnn號(hào)島嶼的時(shí)候,身上必須有附魔才能成功逃離,問(wèn)成功逃離的概率
    解決這個(gè)問(wèn)題需要幾個(gè)知識(shí)點(diǎn)

鄰接矩陣k次方的結(jié)論

  • 如果從iiijjj有路徑,則設(shè)a[i][j]=1a[i][j]=1a[i][j]=1,則矩陣ak[i][j]a^k[i][j]ak[i][j]表示從iiijjj經(jīng)過(guò)kkk條路徑的通路總數(shù)

拆點(diǎn)法

  • 將每一個(gè)點(diǎn)拆成兩個(gè)點(diǎn),分別為有附魔的和沒(méi)附魔的,可以分別表示為iiii+ni+ni+n,見下圖
  • 上面表示帶附魔的,如果iii經(jīng)過(guò)一條普通邊,只需要在同側(cè)連邊;如果經(jīng)過(guò)附魔邊,則連向另外一側(cè)
  • 這樣以后只需要填充鄰接矩陣先計(jì)算出所有點(diǎn)的度數(shù),接下來(lái)根據(jù)每個(gè)點(diǎn)的的度數(shù)計(jì)算對(duì)模的逆元,之后進(jìn)行矩陣快速冪計(jì)算即可
#include <iostream> #include <cstring> #include <algorithm> #include <queue> #include <stack> #include <vector> #include <cmath> #include <cstdio> #include <map> using namespace std; typedef long long ll; const int MAXN = 333; const ll MOD = 998244353; inline int read(){int x = 0, f = 1;char c = getchar();while(c < '0' || c > '9'){if(c == '-') f = -1;c = getchar();}while(c >= '0' && c <= '9'){x = (x << 1) + (x << 3) + (c ^ 48);c=getchar();}return x*f; } struct Matrix{ll m[MAXN][MAXN];Matrix(){memset(m, 0, sizeof m);} }; Matrix mul(Matrix a, Matrix b, int n){Matrix ans;for(int i=1;i<=n;i++){for(int j=1;j<=n;j++){for(int k=1;k<=n;k++){ans.m[i][j] = (ans.m[i][j] + a.m[i][k] * b.m[k][j]) % MOD;}}}return ans; } Matrix fastpow(Matrix base, int power, int n){Matrix ans;for(int i=1;i<=n;i++) ans.m[i][i] = 1;while(power){if(power & 1) ans = mul(ans, base, n);base = mul(base, base, n);power >>= 1;}return ans; } void extend_gcd(ll a, ll b, ll &x, ll &y){if(b == 0){x = 1;y = 0;return;}extend_gcd(b, a % b, x, y);ll tmp = x;x = y;y = tmp - a / b * y; } ll inverse_mod(ll y, ll p){ll x, m;extend_gcd(y, p, x, m);return (p + x % p) % p; } int degree[MAXN]; ll inv[MAXN]; int main(){int t, n, m, k, u, v, w;t = read();while(t--){n = read();m = read();k = read();Matrix edge, mp;for(int i=0;i<m;i++){u = read();v = read();w = read();edge.m[u][v] = w + 1;edge.m[v][u] = w + 1;}for(int i=1;i<=n;i++){for(int j=1;j<=n;j++){if(edge.m[i][j] == 2){++degree[i];++degree[j];++degree[i + n];++degree[j + n];}else if(edge.m[i][j] == 1) {++degree[i];++degree[j];++degree[i + n];++degree[j + n];}}}for(int i=1;i<=n;i++){degree[i] >>= 1;inv[i] = inverse_mod(degree[i], MOD);degree[i] = degree[i + n] = 0;}for(int i=1;i<=n;i++){for(int j=1;j<=n;j++){if(edge.m[i][j] == 1){mp.m[i][j] = inv[i];mp.m[i + n][j + n] = inv[i];}else if(edge.m[i][j] == 2){mp.m[i + n][j] = inv[i];mp.m[i][j + n] = inv[i];}}}mp = fastpow(mp, k, 2 * n);cout << mp.m[1][2 * n] << '\n';}return 0; }
  • 樣例沒(méi)問(wèn)題不過(guò)交在HDU上面返回TLE,標(biāo)程就是這個(gè)思路,可能是評(píng)測(cè)機(jī)的問(wèn)題吧,我用榜111的代碼交了也是TLE,聽說(shuō)用矩陣計(jì)算這里用更高級(jí)的辦法能把時(shí)間優(yōu)化到500ms500ms500ms以下??

1003鴿子

  • 設(shè)dp[i]dp[i]dp[i]表示當(dāng)前操作壞的電腦位置在iii的最少操作次數(shù),那么因?yàn)楫?dāng)前操作是交換iiijjj,所以有dp[i]=min(dp[i]+1,dp[j])dp[i]=min(dp[i]+1,dp[j])dp[i]=min(dp[i]+1,dp[j])dp[j]=min(dp[j]+1,dp[i])dp[j]=min(dp[j]+1,dp[i])dp[j]=min(dp[j]+1,dp[i])
  • 很容易理解,注意更新不要覆蓋
#include <iostream> #include <cstring> #include <algorithm> #include <queue> #include <stack> #include <vector> #include <cmath> #include <cstdio> #include <map> using namespace std; typedef long long ll; const int MAXN = 2e5 + 100; const int INF = 0x3f3f3f3f; int Data[MAXN]; int dp[MAXN]; int main(){ios::sync_with_stdio(false);int t, n, m, k, u, v;cin >> t;while(t--){cin >> n >> m >> k;memset(dp, 0x3f, sizeof dp);dp[k] = 0;for(int i=1;i<=m;i++){cin >> u >> v;int a = dp[u];int b = dp[v];dp[v] = min(b + 1, a);dp[u] = min(a + 1, b);}for(int i=1;i<=n;i++){if(i != 1) cout << ' ';cout << (dp[i] == INF ? -1 : dp[i]);}cout << '\n';}return 0; }

1004萌新

  • 已知aaabbbccc同余,給定aaabbb,讓求ccc的最小和最大值,滿足c?1>0c-1\gt0c?1>0c≤max(a,b)c\leq max(a,b)cmax(a,b)
  • 現(xiàn)在假定a>ba\gt ba>b,顯然有a?b=kca-b=kca?b=kc,那么c最大時(shí)候顯然是kckckc也就是a?ba-ba?b,但是這里需要注意兩種特殊情況分別是a?b=1a-b=1a?b=1a?b=0a-b=0a?b=0;當(dāng)求c最小的時(shí)候只需要枚舉a?ba-ba?b的每個(gè)因子,找到最小即可,但是需要注意特判a=1,b=1a=1,b=1a=1,b=1的兩種情況
#include <iostream> #include <cstring> #include <algorithm> #include <queue> #include <stack> #include <vector> #include <cmath> #include <cstdio> #include <map> using namespace std; typedef long long ll; const int MAXN = 2e5 + 100; const int INF = 0x3f3f3f3f; int Data[MAXN]; int main(){ios::sync_with_stdio(false);int t;ll a, b;cin >> t;while(t--){cin >> a >> b;if(a < b) swap(a, b);ll c = a - b;if((a == 1 && b == 1) || c == 1){cout << -1 << " " << -1 << '\n';continue;}if(a == b){cout << 2 << " " << a << '\n';continue;}int f = 0;for(ll i=2;i*i<=c;i++){if(c % i == 0){cout << i << " ";f = 1;break;}}if(f) cout << c << '\n';else cout << c << ' ' << c << '\n';}return 0; }

1006毒瘤數(shù)據(jù)結(jié)構(gòu)題

  • 考察思維,用兩個(gè)指針維護(hù)最左邊的兩個(gè)0,對(duì)于操作1,如果修改了第一個(gè)0,則更新最左邊兩個(gè)0的位置,如果修改了第二個(gè)0,則更新第二個(gè)0的位置,其他情況正常標(biāo)記;對(duì)于操作2,如果查詢到第一個(gè)0,那么答案為第二個(gè)0的位置,其他情況答案都為第一個(gè)0的位置
  • 在HDU上必須用超級(jí)快讀才能過(guò)得了
#include <iostream> #include <algorithm> #include <cstring> #include <cstdio> #include <vector> #include <cmath> #include <queue> #include <stack> #include <map> #include <iomanip> using namespace std; typedef long long ll; typedef unsigned long long ull; const int INF = 0x3f3f3f3f; const int MAXN = 1e7 + 100; const double eps = 1e-6; int vis[MAXN]; inline int read(){int x = 0, f = 1;char c = getchar();while(c < '0' || c > '9'){if(c == '-') f = -1;c = getchar();}while(c >= '0' && c <= '9'){x = (x << 1) + (x << 3) + (c ^ 48);c = getchar();}return x * f; } namespace IO{inline char nc(){static char buf[100000], *p1 = buf, *p2 = buf;return p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 100000, stdin), p1 == p2) ? EOF : *p1++;}template<typename T>inline T read(){char ch = nc();T sum = 0;while(ch < '0' || ch > '9'){ch = nc();if(ch == EOF) return EOF;}while(ch >= '0' && ch <= '9'){sum = (sum << 1) + (sum << 3) + (ch ^ 48);ch = nc();if(ch == EOF) return EOF;}return sum;} } int main(){ios::sync_with_stdio(false);int n, a, b;n = IO::read<int>();int x, y;x = 1;y = 2;for(int i=0;i<n;i++){a = IO::read<int>();b = IO::read<int>();if(a == 1){vis[b] = 1;if(b == y){while(vis[y]) ++y;}else if(b == x){x = y;++y;while(vis[y]) ++y;}}else{if(b == x) printf("%d\n", y);else printf("%d\n", x);}} return 0; }

1008獵人殺

  • 狼人先殺人(也可能自刀),之后獵人開槍互相殺,直到殺死狼或者剩下人數(shù)不大于2
  • 暴力模擬即可
#include <iostream> #include <algorithm> #include <cstring> #include <cstdio> #include <vector> #include <cmath> #include <queue> #include <stack> #include <map> #include <iomanip> using namespace std; typedef long long ll; typedef unsigned long long ull; const int INF = 0x3f3f3f3f; const int MAXN = 1e6 + 100; const double eps = 1e-6; int main(){ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);int t, n, x;cin >> t;while(t--){cin >> n;int id = -1;for(int i=1;i<=n;i++){cin >> x;if(x == 1) id = i;}vector<vector<int> > vs(n + 5);vector<int> vis(n + 5);for(int i=1;i<=n;i++){for(int j=1;j<=n;j++){cin >> x;vs[i].push_back(x);}}int ok = 0;int now = vs[id][0];int res = n - 1;vis[now] = 1;if(now == id){ok = 2;}else if(res <= 2){ok = 1;}else{while(1){if(ok) break;for(int i=0;i<vs[now].size();i++){int to = vs[now][i];if(vis[to] || to == now) continue;vis[to] = 1;now = to;--res;if(now == id){ok = 2;}else if(res <= 2){ok = 1;}break;} }}cout << (ok == 1 ? "langren" : "lieren") << '\n';}return 0; }

總結(jié)

以上是生活随笔為你收集整理的2021百度之星程序设计大赛-初赛一部分题目总结的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。