生活随笔
收集整理的這篇文章主要介紹了
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
;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
;}ll ans
= 0;sort(a
, a
+ n
);pos
[a
[0]]++;ans
++;for (int i
= 1; i
< n
; i
++) {if (pos
[a
[i
]] < pos
[a
[i
- 1]])pos
[a
[i
]] = pos
[a
[i
- 1]];if (pos
[a
[i
]] <= a
[i
] + k
) {pos
[a
[i
]]++;ans
++; }else {}}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
++;degree
[i
]++; degree
[j
+ 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;}}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
++;if (whi
)whi
+= 2 * (cnt
- 1);cout
<< whi
<< "\n";}else {cout
<< -1 << "\n";}}}
the end。
總結
以上是生活随笔為你收集整理的2021百度之星初赛二(1001 -- 1003)的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。