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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

Codeforces Gym - 100917 部分题解

發布時間:2023/12/3 编程问答 44 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Codeforces Gym - 100917 部分题解 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

A.Abstract Picture Gym - 100917A

分析:由于最后刷的一筆肯定使得某一行或者是某一列均為相同的顏色。
因此我們可以在一開始找到所有的行或者列,他們的顏色全都一樣,把這樣的行或列加入到隊列里面去。
我們處理在隊列里面的行或者列:把它取出來,并且把該筆刷成的顏色全都變成’?’(即可變顏色)。然后檢查是否有新的行或者列變成顏色均相同了,如果有的話,繼續加入隊列中進行處理。
隊列出隊的順序反過來即為答案。
具體實現細節略。


F - Find the Length Gym - 100917F

分析:因為不存在重復邊,那么一個最短簡單環,至少需要有三個點組成,而刪掉最短簡單環上的一條邊uvuv那么剩下的一條路徑一定是刪去uvuv之后的從uuvv的最短路。
對于一定包含點ss的最短簡單環,我們枚舉這里面假裝刪掉的那條邊,那么會出現下面兩種情況
一、這條邊的一個端點是ss
這種情況下,設另一端的端點為tt,如果sstt的最短路就不是這條邊,那么很好,從sstt的最短路++stst就是一個可行結果,更新包含ss的最短簡單環答案;而如果從sstt的最短路就是這條邊,那么這種情況我們直接扔掉,不做處理,因為這種情況可以由枚舉其他邊的時候解決。
二、這條邊的兩個端點uvu、v均非ss
這種情況下,從uuvv的最短路還要包含ss,那么只能是從uuss的最短路++vvss的最短路,這里千萬要注意兩條最短路不能有重復邊。否則從uuvv的最短路將不會包含點ss
具體做法:
枚舉點ss,跑一邊Dijkstra,得到一顆最短路徑樹,然后根據第一種情況更新一次答案。根據第二種情況更新答案的時候注意,判斷兩條路不包含重復邊的方法可以用lcalca,當然也可以用其他的方法。

#include <iostream> #include <cstdio> #include <queue> using namespace std; typedef pair<int,int> pii; const int N = 400; const int inf = 1e8; int dist[N]; int G[N][N]; int n; int fa[N]; int find(int x){return x == fa[x] ? x : fa[x] = find(fa[x]); } void dij(int s){for(int i = 1;i <= n;++i) dist[i] = inf,fa[i] = i;dist[s] = 0;priority_queue<pii> Q;Q.push({0,s});while(!Q.empty()){pii p = Q.top();Q.pop();int u = p.second;int d = -p.first;if(d > dist[u]) continue;for(int v = 1;v <= n;++v){if(v == u) continue;if(dist[v] > dist[u] + G[u][v]){dist[v] = dist[u] + G[u][v];if(u != s) fa[v] = u;Q.push({-dist[v],v});}}} } #define pr(x) cout<<#x<<":"<<x<<endl int main(){cin>>n;for(int i = 1;i <= n;++i){for(int j = 1;j <= n;++j){scanf(" %d",&G[i][j]);if(G[i][j] == -1) G[i][j] = inf;}}for(int s = 1;s <= n;++s){int ans = inf;dij(s);for(int i = 1;i <= n;++i){if(fa[i] != i){if(dist[i] + G[i][s] < ans)ans = dist[i] + G[i][s];}}for(int i = 1;i <= n;++i){if(i == s) continue;for(int j = 1;j <= n;++j){if(j == s || find(i) == find(j)) continue;if(dist[i]+dist[j]+G[i][j] < ans)ans = dist[i]+dist[j]+G[i][j];}}ans = ans == inf ? -1:ans;printf("%d\n",ans);}return 0; }

I - Interactive Casino Gym - 100917I

這道題很有意思。
我們把所有的種子每個都用隨機數生成器計算出前幾個值,并把每個值得到的輸贏用01串存起來,實踐發現當計算到第38層的時候,我們就可以把每個種子的01串給區分開了。對于每個種子,01串的長度為38。
我們將這所有的01串放入一個Trie樹里面去。一開始一直用猜1來試,可以根據反饋結果確定這次的位。38輪以后我們就可以找得到隨機數種子了。找到隨機數種子這道題基本就結束了。


J - Judgement Gym - 100917J

我們用背包dp求出在第一種方案下的權值和為s1s1時候所能得到第二種方案下權值和的最大值s2s2,只要出現s1<ps1<ps2>=qs2>=q的情況,那么就輸出”NO”并且打印方案。反過來再做一遍就好了。
這里注意這道題要使用滾動數組,這樣的話記錄方案就會變得麻煩,為了保存信息,需要使用一個長為100的bitset來存方案。

#include <iostream> #include <cstdio> #include <assert.h> #include <cstring> #include <bitset> using namespace std; const int N = 1e6+10; int n,upb[2],val[2][N]; int dp[2][N]; bitset<101> way[2][N]; int vis[111]; int main(){scanf("%d",&n);scanf("%d",&upb[0]);for(int i = 1;i <= n;++i) scanf("%d",&val[0][i]);scanf("%d",&upb[1]);for(int i = 1;i <= n;++i) scanf("%d",&val[1][i]);int cc = 0 ;for(int cas = 0;cas < 2;++cas){for(int i = 1;i <= n;++i){for(int j = upb[cas]-1;j >= val[cas][i];j--){if(dp[cas][j-val[cas][i]] + val[cas^1][i] > dp[cas][j]){dp[cas][j] = dp[cas][j-val[cas][i]] + val[cas^1][i];//map[cas][j] = i;way[cas][j] = way[cas][j-val[cas][i]];way[cas][j].set(i); if(dp[cas][j] >= upb[cas^1]){//output(cas,j);puts("NO");for(int i = 1;i <= n;++i){cout<<way[cas][j][i];}return 0;}}}}}puts("YES");return 0; }

總結

以上是生活随笔為你收集整理的Codeforces Gym - 100917 部分题解的全部內容,希望文章能夠幫你解決所遇到的問題。

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