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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

2021百度之星初赛二(1001 -- 1003)

發布時間:2024/1/1 编程问答 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 2021百度之星初赛二(1001 -- 1003) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

2021百度之星初賽二(1001 – 1003)

1001
題意:
給 a,b,每次 a,b會變為 a+b,a-b,問 k 次之后變成了哪兩個數,對 998244353998244353 取模,多組數據。
題解:
首先觀察前幾次變化,
0 -------- a b 1 -------- a - b a + b
2 -------- 2a 2b 3 -------- 2a - 2b 2a + 2b
……
不難發現
對于k為偶數,答案是 a * pow(2,k/2) b * pow(2,k/2);
對于k為奇數,答案是 (a-b) * pow(2,(k-1)/2) (a+b) * pow(2,(k-1)/2);
ps:由于k可以達到1e9,因此使用快速冪。

#include <vector> #include <string> #include <cstdio> #include <cmath> #include <iostream> #include <algorithm> #include <stack> #include <cstring> #include <map> #define INF 0x3f3f3f3f #define ll long long const double pi = acos(-1.0); using namespace std; const ll mod = 998244353;ll qpow(ll a, ll b) {ll ans = 1;while (b) {if (b & 1) {ans = (ans * a) % mod;}b >>= 1;a = (a * a) % mod;}return ans; } int main() {int t; cin >> t;while (t--) {ll a, b, c, d;cin >> a >> b;c = (a + b) % mod;d = (a - b + mod) % mod;//這里的mod一定要加,像我不加卡半小時ll k; cin >> k;ll s = k / 2;ll e = k % 2;ll pre = qpow(2, s);ll ans1, ans2;if (e & 1) {ans1 = (c * pre) % mod;ans2 = (d * pre) % mod;}else {ans1 = (a * pre) % mod;ans2 = (b * pre) % mod;}cout << ans1 << " " << ans2 << endl;} }

1002
題意:

題解:
根據題意,可以發現a[n]的排列順序對答案是不會產生影響的
比如 a={ 2, 3 },k = 1, 那么一種構造為b={1, 2},x=2;
現在改變a的順序為{3,2},那么相應的b={2,1},x=2;
因此,不妨把a變為一個升序序列,為了使b的數字種類夠多,可以在構造b時,往小處取值,并保證數字種類的不同。這樣構造出來的b也是一個升序序列。
這里可以使用map,用于表示對于某種數字,當前可以使用的最小值。

#include <vector> #include <string> #include <cstdio> #include <cmath> #include <iostream> #include <algorithm> #include <stack> #include <map> #include <set> #define INF 0x3f3f3f3f #define ll long long const double pi = acos(-1.0); using namespace std; const ll mod = 998244353; ll a[100005]; map<ll, ll> pos; int main() {ios::sync_with_stdio(0);cin.tie(0); cout.tie(0);int t; cin >> t;while (t--) {int n; cin >> n;ll k; cin >> k;pos.clear();for (int i = 0; i < n; i++) {cin >> a[i];pos[a[i]] = a[i] - k;//該數字初始可使用的最小值一定是 數字-k}ll ans = 0;sort(a, a + n);//a[0] = pos[a[0]];pos[a[0]]++;//第一位的最小值選定,可選最小值加1ans++;for (int i = 1; i < n; i++) {//如果當前數字的可選最小值比上個數字小,表明當前最小值不符合條件,必然和之前數字有重復//因此要進行更新if (pos[a[i]] < pos[a[i - 1]])pos[a[i]] = pos[a[i - 1]];//在沒超過k的范圍內,數字種類可增加,并更新可選最小值if (pos[a[i]] <= a[i] + k) {pos[a[i]]++;//a[i] = pos[a[i]] - 1;ans++; }else {//a[i] = pos[a[i]] - 1;}}cout << ans << "\n";} }

1003
題意:
給一張無向完全圖,每條邊有一個顏色,為黑色或者白色。你初始在點 s 上,你每次可以從當前的點經過一條邊走到另一個點上,并將走過的邊的顏色翻轉。你想要把圖中所有的邊全都變為黑色,要求最小化走過的邊的條數,求這個最小值,或者判斷無解。
題解:
首先,題中所給的圖是完全圖,則必然是簡單圖,且每兩點之間都有邊相連。
要把所有白邊變為黑邊,白邊要經過奇數次,黑邊變為黑邊,黑邊要經過偶數次。為了使次數減少,那么原題可變為所有白邊都經過1次并且借助最少的黑邊的方案。
我們可以先把所有白邊單獨構圖,作為一個白邊子圖。這樣你會得到幾個僅有白邊的連通分量。為了使所有白邊能經過,每兩個連通分量間用黑邊連接。由于是完全圖,這樣的黑邊是必然存在的。
黑邊要經過兩次,因此加入到白邊圖中就等價于一對白色重邊。
這樣其實就構造好了一張連通的白邊子圖,這張子圖的總邊數就是我們要的答案。
但這個子圖不一定是能達到要求的。子圖所有邊都是要不重復經過一次的,那就要用歐拉定理來判斷。
這里說明一下,之前加黑邊的操作是為了更好理解。判斷是否為歐拉圖/半圖,初始的白邊圖就行。因為黑邊只會給節點的度數加2,這不影響節點的奇偶性。
如果這不是歐拉圖/半圖,可以判為不可行。如果是歐拉圖,那一定要判斷起點是否為孤立節點,如果孤立,則必須與白邊子圖間用黑邊連接。如果是歐拉半圖,要是起點的度數不是奇數,則判為不可行。
圖利用并查集儲存。

#include <vector> #include <string> #include <cstdio> #include <cmath> #include <iostream> #include <algorithm> #include <stack> #include <map> #include <set> #include <cstring> #define INF 0x3f3f3f3f #define ll long long const double pi = acos(-1.0); using namespace std; const ll mod = 998244353; int degree[1005]; //========================================== int net1[100010]; int afind1(int i) {if (net1[i] == i)return i;else return net1[i] = afind1(net1[i]); } void u1(int x, int y) {if (afind1(x) != afind1(y))net1[afind1(x)] = afind1(y);else return; } //============================================== int net2[100010]; int afind2(int i) {if (net2[i] == i)return i;else return net2[i] = afind2(net2[i]); } void u2(int x, int y) {if (afind2(x) != afind2(y))net2[afind2(x)] = afind2(y);else return; } //==============================================int main() {ios::sync_with_stdio(0);cin.tie(0); cout.tie(0);int t; cin >> t;while (t--) {int n; cin >> n;int str; cin >> str;memset(degree, 0, sizeof degree);for (int i = 0; i <= n; i++) {net1[i] = net2[i] = i;}int whi = 0;for (int i = 2; i <= n; i++) {string a; cin >> a;for (int j = 0; j < a.length(); j++) {if (a[j] == '0') {u1(i, j + 1);//構造白邊子圖。whi++;//白邊加1degree[i]++; degree[j + 1]++;//對應節點度數加1}else {u2(i, j + 1);//構造黑邊子圖,這個應該不需要,請忽略。}}}bool f = 1; int jie = 0;for (int i = 1; i <= n; i++) {if (degree[i] & 1)jie++;}if (!(jie == 0 || jie == 2))f = 0;//判斷是否為歐拉圖/半圖if (f) {if (jie == 2) {if (!(degree[str] & 1))f = 0;//半圖且起點度數不為奇數,不可行}}//cout << degree[1] << degree[2] << endl;if (f) {bool che[1005] = { 0 };for (int i = 1; i <= n; i++) {if (degree[i])che[afind1(i)] = 1;//孤立節點不判斷為一個連通分量}int cnt = 0;for (int i = 1; i <= n; i++) {if (che[i])cnt++;//連通分量計數}if (degree[str] == 0)cnt++;//如果起點孤立,起點也作為一個連通分量//cout << whi << " :" << cnt << endl;if (whi)whi += 2 * (cnt - 1);//白邊數加所需的黑邊數的兩倍cout << whi << "\n";}else {cout << -1 << "\n";}}}

the end。

總結

以上是生活随笔為你收集整理的2021百度之星初赛二(1001 -- 1003)的全部內容,希望文章能夠幫你解決所遇到的問題。

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