VJ
409组队赛2
C - Find a Number
没想到这是一个签到题,因为数据量小,状态并不多,所以可以使用
b
f
s
bfs
bfs 去跑每一个状态。令
m
o
d
mod
mod 是余数,
s
u
m
sum
sum 是累加和,那么状态最多就只有
500
∗
5000
500 * 5000
500∗5000 种状态。可以
b
f
s
bfs
bfs。
但是要注意的地方是,
b
f
s
bfs
bfs 在标记是否遍历过时,应在入队的时候就进行标记,而不是在出队的时候再进行标记,不然会重复入队造成
M
L
E
MLE
MLE 或者
T
L
E
TLE
TLE。
代码如下:
#include<bits/stdc++.h>
using namespace std;
const int N = 500+5;
typedef pair<int, int>PII;
int T, n, m;
bool st[N][N*10];
struct node
{
int mod, s;
string ans;
};
queue<node>q;
string bfs()
{
q.push({0, 0, ""});
st[0][0] = true;
while(q.size())
{
int t1 = q.front().mod, t2 = q.front().s;
string s = q.front().ans;
q.pop();
if(t1 == 0 && t2 == m) return s;
for(int i = 0; i < 10; i ++)
{
int z1 = (t1*10 + i) % n, z2 = t2 + i;
if(z2 <= m && !st[z1][z2])
{
st[z1][z2] = true;
q.push({z1, z2, s + (char)(i + '0')});
}
}
}
return "-1";
}
signed main()
{
ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
cin >> n >> m;
cout << bfs() << '\n';
}
H - Tower
这个题实属没想到可以这样暴力写
代码如下:
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int Max = 0x3f3f3f3f3f3f3f3f;
const int Min = -0x3f3f3f3f3f3f3f3f;
const int N = 2e5+5;
typedef pair<int, int>PII;
int T, n, m;
int q[N], a[N];
signed main()
{
ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
cin >> T;
while(T --)
{
set<int>se;
cin >> n >> m;
for(int i = 0; i < n; i ++)
{
cin >> a[i];
int x = a[i];
while(x)
{
se.insert(x);
x /= 2;
}
}
int ans = Max;
for(auto it : se)
{
int cnt = 0, res = 0;
for(int i = 0; i < n; i ++)
{
if(a[i] <= it) q[cnt ++] = it - a[i];
else
{
int x = a[i], tt = 0;
while(x / 2 >= it)
{
tt ++;
x /= 2;
}
tt += min(abs(it - x), 1 + it - x / 2);
q[cnt ++] = tt;
}
}
sort(q, q+cnt);
for(int i = 0; i < cnt - m; i ++)
{
res += q[i];
}
ans = min(ans, res);
}
cout << ans << '\n';
}
}
牛客
第十一届"图灵杯"NEUQ-ACM程序设计竞赛
古希腊掌管原神的神
这个题出的是真烂啊,题目也并没有说明,我们知不知道谁是真神或者是假神什么的。这个题最关键的一点就在于我们并不知道自己问的神他是真还是假还是变化神。所以只有当真神数量大于假神和变化神数量之和时,才能确定哪个是原神。因为在最坏的清况下我们问的
b
+
c
b + c
b+c 个神说的都是假话,假设都说原神是
x
x
x 吧;剩下的都是真神了,当再问
b
+
c
+
1
b + c + 1
b+c+1 个神之后,都说原神是
y
y
y,这时候根据数量的大小,就能辨别哪一个是原神了。
最后再特判一下当只有一个神的时候,一次也不用问就可以确定。
代码如下:
#include<bits/stdc++.h>
using namespace std;
const int N = 2e5+5;
typedef pair<int, int>PII;
int T, n, m;
signed main()
{
ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
int a, b, c;
cin >> a >> b >> c;
if(a + b + c == 1)
{
cout << "YES\n";
cout << 0 << '\n';
return 0;
}
if(a > b + c)
{
cout << "YES\n";
cout << (b+c)*2+1 << '\n';
return 0;
}
cout << "NO\n";
return 0;
}
牛客小白月赛88
多重映射
这个题,看完题解后就恍然大悟了,当时时间不多了,也没仔细想。这个题要倒着考虑,从后向前做一个并查集就可以了。例如
7
7
7 变
5
5
5 然后
5
5
5 变
3
3
3,那么就让
p
[
5
]
=
3
,
p
[
7
]
=
p
[
5
]
p[5] = 3,p[7] = p[5]
p[5]=3,p[7]=p[5]。
唯一要注意的地方就是,这个是多组输入,不能每次都用
m
e
m
s
e
t
memset
memset 来进行初始化,题解是用
m
a
p
map
map 处理,但是可以直接把出现的数字存入
v
e
c
t
o
r
vector
vector 中,只对
v
e
c
t
o
r
vector
vector 内的数字初始化就可以了,但是记得每次清空
v
e
c
t
o
r
vector
vector。
注意把数组大小开到
1
0
6
10^6
106。
代码如下:
#include<bits/stdc++.h>
using namespace std;
const int N = 1e6+5;
typedef pair<int, int>PII;
int T, n, m;
int a[N], f[N];
PII p[N];
vector<int>v;
signed main()
{
ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
cin >> T;
while(T --)
{
cin >> n >> m;
for(int i = 0; i < n; i ++)
{
cin >> a[i];
}
for(int i = 0; i < m; i ++)
{
int x, y;
cin >> x >> y;
p[i] = {x, y};
v.push_back(x), v.push_back(y);
}
for(int i = m - 1; i >= 0; i --)
{
int t1 = p[i].first, t2 = p[i].second;
if(f[t2] != 0) f[t1] = f[t2];
else f[t1] = t2;
}
for(int i = 0; i < n; i ++)
{
if(f[a[i]]) cout << f[a[i]];
else cout << a[i];
if(i != n - 1) cout << " ";
else cout << '\n';
}
for(auto it : v) f[it] = 0;
v.clear();
}
return 0;
}