2023牛客寒假算法基础集训营1
题目 | 类型 | 官方 |
---|---|---|
A | 贪心 | 模拟 |
L | 期望 | 数学 |
C | 贪心 | 诈骗 思维 贪心 |
H | 思维 | 诈骗 思维 贪心 |
K | 贪心 | 贪心 or 状压dp |
D | 思维 | 贪心 数学 分类讨论 |
A World Final? World Cup! (I)
贪心:即使输方后面全得也没有办法追平分数
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-kf8dxd8W-1674918506201)(image-ldf9f79o.png)]
#include <bits/stdc++.h>
#define rep(i, a, b) for(int i = a; i <= b; i ++ )
#define fors(i, a, b) for(int i = a; i < b; i ++ )
#define deb(x) cout << #x << "=" << x << endl
#define deb2(x, y) cout << #x << "=" << x << ", " << #y << "=" << y << endl
using namespace std;
const int N = 2e5 + 10, mod = 1e9+7;
char a[6], b[6];
typedef pair<int, int> PII;
typedef long long ll;
bool check(int sca, int scb, int k) {
if(sca > scb) { // b翻盘的机会
if((k + 1) /2 < (sca - scb)) {
cout << 10 - k << endl;
return 1;
}
}
if(sca < scb) { // a翻盘的机会
if(k/2 < (scb - sca)) {
cout << 10 - k << endl;
return 1;
}
}
return 0;
}
void run() {
int k = 10, sca = 0, scb = 0, flag = 0;
rep(i, 1, 5) cin >> a[i], cin >> b[i];
rep(i, 1, 5) {
// 第一次
if(a[i] == '1') sca += 1;
k -= 1;
if(check(sca, scb, k)) {
flag = 1;
break;
}
// 第二次
if(b[i] == '1') scb += 1;
k -= 1;
if(check(sca, scb, k)) {
flag = 1;
break;
}
}
if(flag == 0) cout << -1 <<endl;
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0);
int T = 1;
cin >> T;
while(T -- ) run();
return 0;
}
L 本题主要考察了运气
期望
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-iRzzncpi-1674918506202)(image-lde1rav7.png)]
C 现在是,学术时间 (I)
贪心
#include <bits/stdc++.h>
using namespace std;
signed main() {
int t = 1;
cin >> t;
while(t -- ) {
int n, i, x, sum = 0; cin >> n;
for (i = 1; i <= n; i ++ ) {
cin >> x;
if(x != 0) sum += 1;
}
cout << sum << endl;
}
}
H 本题主要考察了DFS
思维:[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-VON548K5-1674918506202)(image-lde48rn5.png)]
:::note
标记技巧:一个拼图块可以由一个长度为4的字符串描述,四个字符分别表示上、右、下、左四条边进行的操作,上述三种操作依次记为0,1,2、
:::
#include <iostream>
using namespace std;
void run() {
int n, i, x = 0, y = 0; cin >> n;
char ch;
for (i = 1; i <= n*n*4 - 4; i ++ ) {
cin >> ch;
if(ch == '1') x += 1;
if(ch == '2') y += 1;
}
cout << 10 + x - y << endl;
}
int main() {
int t; cin >> t;
while(t -- ) run();
}
K 本题主要考察了dp
贪心
#include <iostream>
#define deb(x) cout << #x << "=" << x << endl
#define deb2(x, y) cout << #x << "=" << x << ", " << #y << "=" << y << endl
using namespace std;
signed main() {
int n, m, x; cin >> n >> m;
x = n - m; // m-1, x-0
if(m <= n/3) cout << 0 << endl;
else if(n == m) cout << n-2 << endl;
else {
m -= x/2;
x = x%2;
//deb2(m,x);
if(x == 0 && m == 1) cout << 0 << endl;
else cout << m - 2 + 1;
}
}
D 现在是,学术时间 (II)
思维:(看)先求出另外矩形的大小,在求交集, s = s= s=两个矩形 − - −交集
#include <bits/stdc++.h>
using namespace std;
void run() {
int x, y, xp, yp, s, a, b;
cin >> x >> y >> xp >> yp;
a = max(abs(xp - x), xp);
b = max(abs(yp - y), yp);
s = a * b + x * y;
a = min(a, x);
b = min(b, y);
double ans;
ans = double(a * b) / (s - a * b);
printf("%.9f\n", ans);
}
int main() {
int t = 1;
cin >> t;
while(t-- ) run();
}
题目 | 类型 | 官方 |
---|---|---|
M | dp | dp(背包) |
F | 图论 | 思维 基础图论 BFS |
M 本题主要考察了找规律
就是很典型的dp,枚举一下就可以了
#include <bits/stdc++.h>
using namespace std;
double dp[510][510]; // 前i个人共分得j个仙贝的最大好感度
signed main() {
int n, m, i, j, k; cin >> n >> m;
for (i = 1; i <= n; i ++ )
for (j = 1; j <= m; j ++ )
for (k = 1; k <= j; k ++ )
dp[i][j] = max(dp[i][j], dp[i-1][j-k] + k*1.0 / (m - j + k));
printf("%.9lf", dp[n][m]);
}
F 鸡玩炸蛋人
图论+结论+转化 [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-FrTrXueM-1674918506203)(image-ldfcjo5j.png)]
:::danger
开不了这么大的内存,白写
:::
#include <bits/stdc++.h>
using namespace std;
int g[100010][100010];
int vis[100010];
int w[100010];
int n;
typedef pair<long long, bool> PII;
PII bfs(int s) {
int i;
queue<int> q; q.push(s);
PII t = {0, 0};
while(!q.empty()) {
int k = q.front();
for (i = 1; i <= n; i ++ ) {
if(g[k][i] == 1 && vis[i] == 0) {
vis[i] = 1;
q.push(i);
t.first += 1;
if(w[i] != 0) t.second = 1;
}
}
}
return t;
}
signed main() {
int m, i, sum = 0, x, y, flag = 0; cin >> n >> m;
long long ans = 0;
for (i = 0; i < m; i ++ ) {
cin >> x >> y;
g[x][y] = 1, g[y][x] = 1;
}
for (i = 1; i <= n; i ++ ) {
cin >> w[i];
if(w[i] != 0) flag = 1;
}
for (i = 1; i <= n; i ++ ) {
if(vis[i] != 0) { // 如果当前没搜过那就搜完这个连通块
PII t = bfs(i);
if(t.second == 1) ans += t.first * t.first, sum += 1;
}
}
// 第一种:没有砸蛋
if(flag == 1) cout << ans << endl;
// 第二种,有一个连通块有砸蛋
else if(sum == 1) cout << ans << endl;
cout << 1 << endl;
}
:::danger
超时了,可能是map的原因
:::
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-IfiMBtIQ-1674918506203)(image-ldfg5to4.png)]
#include <bits/stdc++.h>
#define deb(x) cout << #x << "=" << x << endl
#define deb2(x, y) cout << #x << "=" << x << ", " << #y << "=" << y << endl
using namespace std;
const int N = 1e5 + 10, M = 4e5 + 10;
int h[N], e[M], ne[N], idx = 0;
int w[N], vis[N], sud;
long long ans, ans2;
map<pair<int, int>, bool> mp;
void bfs(int i) {
long long flag = 0, vsum = 1;
queue<int> q; q.push(i);
vis[i] = 1;
if(w[i] != 0) sud += 1,flag = 1;
while(!q.empty()) {
int t = q.front();
q.pop();
for (int i = h[t]; i != -1; i = ne[i]) {
int y = e[i];
// deb2(t, y);
if(vis[y] == 0) {
vis[y] = 1, vsum += 1;
if(w[i] != 0 && flag == 1) sud += 1, flag = 1;
}
}
}
if(flag == 1) ans2 = vsum * vsum;
ans += vsum * vsum;
// deb2(vsum, ans);
}
void add(int x, int y) {
e[ ++idx] = y, ne[idx] = h[x], h[x] = idx;
// cout << x << ' '<< y<< ' ' << ne[idx] << endl;
}
signed main() {
ios::sync_with_stdio(false);
cin.tie(0);
int n, m, i, x, y; cin >> n >> m;
for (i = 0; i < n; i ++ ) h[i] = -1, vis[i] = 0;
for (i = 0; i < m; i ++ ) {
cin >> x >> y;
if(mp[{x, y}] == 0 && mp[{y, x}] == 0)
{
add(x, y), add(y, x);
mp[{x, y}] = 1; mp[{y, x}] = 1;
}
}
for (i = 1; i <= n; i ++ ) cin >> w[i];
for (i = 1; i <= n; i ++ ) {
if(vis[i] == 0) {
bfs(i);
}
}
if(sud == 0) cout << ans << endl;
if(sud == 1) cout << ans2 << endl;
if(sud > 1)cout << 0 << endl;
}
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll mod=1e9;
const ll mm=2e5+10;
vector<int>v[mm];
int dan[mm],use[mm];
int dfs(int x){
int mi=0;
queue<int>q;
q.push(x);use[x]=1;
while(q.size()){
int now=q.front();
q.pop();
mi++;
for(auto i:v[now]){
if(use[i])continue;
else use[i]=1,q.push(i);
}
}return mi;
}
int main(){
std::ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int n,m;
cin>>n>>m;
for(int i=1;i<=m;i++){
int x,y;
cin>>x>>y;
v[x].push_back(y);
v[y].push_back(x);
}
int mi=0;
for(int i=1;i<=n;i++)cin>>dan[i],mi=max(mi,dan[i]);
if(mi){
ll bj=0;
for(int i=1;i<=n;i++){
if(dan[i]){
bj=dfs(i);
break;
}
}
for(int i=1;i<=n;i++){
if(dan[i]&&use[i]==0){
cout<<0;
return 0;
}
}cout<<bj*bj;
}else{
ll ans=0;
for(int i=1;i<=n;i++){
if(!use[i]){
ll t=dfs(i);
ans+=t*t;
}
}cout<<ans;
}
}
#include<bits/stdc++.h>
#define x first
#define y second
#define int long long
#define io ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
const int N = 1e5 + 10, mod = 1e9 + 7;
using namespace std;
typedef pair<int, int>PII;
int n, p[N], sz[N], m, cnt[N];
int find(int x)
{
if(p[x] != x)
p[x] = find(p[x]);
return p[x];
}
void solve()
{
cin >> n >> m;
for(int i = 1; i <= n; i ++ ) p[i] = i, sz[i] = 1;
while(m -- )
{
int u, v;
cin >> u >> v;
u = find(u), v = find(v);
if(u != v)
{
sz[v] += sz[u];
p[u] = v;
}
}
int x, res = 0;
for(int i = 1; i <= n; i ++ )
{
cin >> x;
if(x) cnt[find(i)] ++, res ++;
}
int ans = 0;
for(int i = 1; i <= n; i ++ )
if(find(i) == i && cnt[i] == res) ans += sz[i] * sz[i];
cout << ans << '\n';
}
signed main()
{
io;
int T = 1;
while(T -- )
solve();
}