title: 2022寒假周赛4
date: 2020-02-19
tags: ACM
A.直角三角形
知识点:二分
思路:直角三角形肯定是三角形,所以只需要判断
a
2
+
b
2
=
c
2
a^2+b^2=c^2
a2+b2=c2。设三边变成分别为a,b,c(c>a,b)所以可知
{
a
2
+
b
2
=
k
2
(
k
>
a
,
b
)
a
2
+
k
2
=
b
2
(
b
>
a
,
k
)
\begin{cases} a^2+b^2=k^2 (k>a,b)\\[2ex] a^2+k^2=b^2 (b>a,k) \end{cases}
⎩⎨⎧a2+b2=k2(k>a,b)a2+k2=b2(b>a,k)
#include <bits/stdc++.h>
using namespace std;
#define LL long long
#define rep(i, a, b) for (int i = a; i < b; i++)
#define per(i, a, b) for (int i = a; i > b; i--)
#define endl '\n'
const int N = 1e5 + 5;
LL a[N], b[N];
int main()
{
int n, k;
while (cin >> n >> k)
{
rep(i, 0, n)
{
cin >> a[i];
b[i] = a[i] * a[i];
}
int ans = k;
int k2 = k * k;
per(i, n - 1, -1)
{
LL t = abs(k2 - b[i]);
int p = lower_bound(b, b + n, t) - b;
if (p != n && b[p] == t)
{
ans += a[i] + a[p];
break;
}
}
if (ans > k)
cout << ans << endl;
else
cout << "no" << endl;
}
return 0;
}
B.数学题
知识点:逆元
思路:勉强过了[doge]
#include <bits/stdc++.h>
using namespace std;
#define LL long long
#define rep(i, a, b) for (int i = a; i < b; i++)
#define per(i, a, b) for (int i = a; i > b; i--)
#define endl '\n'
const LL N = 1e6 + 5, MOD = 1e9 + 7;
LL a[N];
LL qpow(LL a, LL b)
{
LL ans = 1;
while (b)
{
if (b & 1)
ans = ans * a % MOD;
a = a * a % MOD;
b >>= 1;
}
return ans;
}
int main()
{
int n, q;
while (cin >> n >> q)
{
LL ans = 1;
rep(i, 1, n + 1)
{
cin >> a[i];
ans = ans * a[i] % MOD;
}
while (q--)
{
LL x, y;
cin >> x >> y;
ans = ans * qpow(a[x], MOD - 2) % MOD * y % MOD;
a[x] = y;
cout << ans << endl;
}
}
return 0;
}
C.品酒大师(未补)
知识点:拓扑排序
思路:
D.帮派
知识点:并查集
思路:当a和b为兄弟时,直接合并;一个二位数组f存1~n之间每个人各自的敌人id,然后合并fi使f[i][0]和f[i]中的其他的敌人合并。其实我们每次合并的都是f[i][0]和f[i]其他敌人,我们可以在输入时判断当前f[a]是第一次输入,那么我们就使f[a]=b,不然我们就使f[a]和b合并,同理f[b]也是。
#include <bits/stdc++.h>
using namespace std;
#define LL long long
#define rep(i, a, b) for (int i = a; i < b; i++)
#define per(i, a, b) for (int i = a; i > b; i--)
#define endl '\n'
const int N = 1e3 + 5;
int fa[N], ans, fd[N];
void init(int n)
{
rep(i, 1, n)
{
fa[i] = i;
fd[i] = 0;
}
}
int find(int x)
{
return x == fa[x] ? x : (fa[x] = find(fa[x]));
}
void merge(int x, int y)
{
int tx = find(x), ty = find(y);
if (tx != ty)
{
fa[tx] = ty;
ans--;
}
}
int main()
{
int n, m;
while (cin >> n >> m)
{
init(n + 1);
ans = n;
while (m--)
{
char c;
int a, b;
cin >> c >> a >> b;
if (c == 'F')
merge(a, b);
else if (c == 'E')
{
if (fd[a])
merge(fd[a], b);
else
fd[a] = b;
if (fd[b])
merge(fd[b], a);
else
fd[b] = a;
}
}
cout << ans << endl;
}
return 0;
}
E.增增减减
知识点:贪心
思路:使数组a中最大的减,那么只可能出现两种结果,第一种就是全部值
#include <bits/stdc++.h>
using namespace std;
#define LL long long
#define rep(i, a, b) for (int i = a; i < b; i++)
#define per(i, a, b) for (int i = a; i > b; i--)
#define endl '\n'
int main()
{
int n;
while (cin >> n)
{
LL s = 0;
rep(i, 0, n)
{
LL t;
cin >> t;
s += t;
}
LL ans = n - (s % n != 0);
cout << ans << endl;
}
return 0;
}
F.制作字符串
知识点:贪心、暴力
思路:对数组a从小到大排序,并做一个桶数组p,如果ai出现在p中,那么使 a i a_i ai减1,直到ai==0或者从未出现
#include <bits/stdc++.h>
using namespace std;
#define LL long long
#define rep(i, a, b) for (int i = a; i < b; i++)
#define per(i, a, b) for (int i = a; i > b; i--)
#define endl '\n'
const int N = 1e5 + 5;
LL a[N];
LL solve(int n)
{
map<LL, bool> mp;
sort(a, a + n);
LL ans = 0;
rep(i, 0, n)
{
int t = a[i];
if (!mp[t])
{
ans += t;
mp[t] = true;
}
else
per(i, t, -1)
{
if (!mp[i])
{
ans += i;
mp[i] = true;
break;
}
}
}
return ans;
}
int main()
{
int n;
while (cin >> n)
{
rep(i, 0, n) cin >> a[i];
cout << solve(n) << endl;
}
return 0;
}
G.纸飞机
知识点:贪心
思路:每个人制作n架纸飞机需要(n+s-1)/s张白纸t,那么所有人需要k*t张白纸w,那么需要(w+p-1)/p包纸
#include <bits/stdc++.h>
using namespace std;
#define LL long long
#define rep(i, a, b) for (int i = a; i < b; i++)
#define per(i, a, b) for (int i = a; i > b; i--)
#define endl '\n'
int main()
{
int k, n, s, p;
while (cin >> k >> n >> s >> p)
{
int t = (n / s + (n % s != 0)) * k;
int ans = t / p + (t % p != 0);
cout << ans << endl;
}
return 0;
}
H.生日礼物
知识点:贪心
思路:最多的送礼方式是1 2 1这样子送,所以最多可以送(n+2)/3*2次
#include <bits/stdc++.h>
using namespace std;
#define LL long long
#define rep(i, a, b) for (int i = a; i < b; i++)
#define per(i, a, b) for (int i = a; i > b; i--)
#define endl '\n'
int main()
{
int n;
while (cin >> n)
{
int ans = n / 3 * 2 + (n % 3 != 0);
cout << ans << endl;
}
return 0;
}
I.字符串操作
知识点:模拟
#include <bits/stdc++.h>
using namespace std;
#define LL long long
#define rep(i, a, b) for (int i = a; i < b; i++)
#define per(i, a, b) for (int i = a; i > b; i--)
#define endl '\n'
const int N = 1e5 + 5;
int main()
{
string s;
int q;
while (cin >> s >> q)
{
while (q--)
{
string t, s1, s2;
int a, b, c, d;
cin >> t;
if (t == "Append")
{
cin >> s1;
s += s1;
}
else if (t == "Insert")
{
cin >> a >> s1;
s.insert(a - 1, s1);
}
else if (t == "Swap")
{
cin >> a >> b >> c >> d;
a -= 1, b -= 1, c -= 1, d -= 1;
s1 = s.substr(c, d - c + 1);
s2 = s.substr(a, b - a + 1);
s.erase(c, d - c + 1),s.erase(a, b - a + 1);
s.insert(a, s1);
if (s1.size() > s2.size())
{
int t = s1.size() - s2.size();
c += t;
d += t;
}
else if (s1.size() < s2.size())
{
int t = s2.size() - s1.size();
c = max(c - t, 0);
d = max(d - t, 0);
}
s.insert(c, s2);
}
else if (t == "Reverse")
{
cin >> a >> b;
a -= 1, b -= 1;
s2 = s;
while (b > a)
{
s[a] = s2[b];
s[b] = s2[a];
a++, b--;
}
}
}
cout << s << endl;
}
return 0;
}
J.最后一关
知识点:逻辑
思路:我yjw好后悔没做。。。
#include <bits/stdc++.h>
using namespace std;
#define LL long long
#define rep(i, a, b) for (int i = a; i < b; i++)
#define per(i, a, b) for (int i = a; i > b; i--)
#define isLeap(year) (year % 4 == 0 && year % 100 != 0 || year % 400 == 0)
#define endl '\n'
int a[3];
map<string, bool> mp;
void solve(int y, int m, int d)
{
if (m > 12 || m < 1 || d > 31 || d < 1)
return;
y = y <= 59 ? 2000 + y : 1900 + y;
if (m == 2 && d >= 29)
{
if (!(d == 29 && isLeap(y)))
return;
}
string sm = m < 10 ? "0" + to_string(m) : to_string(m);
string sd = d < 10 ? "0" + to_string(d) : to_string(d);
string res = to_string(y) + "-" + sm + "-" + sd;
mp[res] = true;
}
int main()
{
while (scanf("%d/%d/%d", &a[0], &a[1], &a[2]) != EOF)
{
solve(a[0], a[1], a[2]);
solve(a[2], a[0], a[1]);
solve(a[2], a[1], a[0]);
for (auto i = mp.begin(); i != mp.end(); i++)
cout << i->first << endl;
mp.clear();
}
return 0;
}
K.密钥格式化
知识点:模拟题
思路:从后往前
#include <bits/stdc++.h>
using namespace std;
#define LL long long
#define rep(i, a, b) for (int i = a; i < b; i++)
#define per(i, a, b) for (int i = a; i > b; i--)
#define endl '\n'
const int N = 1e5 + 5;
string solve(string s, int n)
{
string ans = "", t = "";
int len = s.size();
per(i, len - 1, -1)
{
if (s[i] != '-')
{
if (islower(s[i]))
s[i] = toupper(s[i]);
t = s[i] + t;
if (t.size() == n)
{
if (ans != "")
ans = "-" + ans;
ans = t + ans;
t = "";
}
}
}
if (t != "")
ans = t + "-" + ans;
return ans;
}
int main()
{
string s;
int n;
while (cin >> s >> n)
cout << solve(s, n) << endl;
return 0;
}
L.命悬一线独木桥
知识点:前缀和
思路:根据题目要求,需要使 a 0 + a 1 + . . . + a ( i − 1 ) = = a ( i + 1 ) + a ( i + 2 ) + . . . + a ( n ) a_0+a_1+...+a_(i-1)==a_(i+1)+a_(i+2)+...+a_(n) a0+a1+...+a(i−1)==a(i+1)+a(i+2)+...+a(n)
#include <bits/stdc++.h>
using namespace std;
#define LL long long
#define rep(i, a, b) for (int i = a; i < b; i++)
#define per(i, a, b) for (int i = a; i > b; i--)
#define endl '\n'
const int N = 1e5 + 5;
LL a[N];
int solve(int n)
{
if (n == 1)
return 1;
rep(i, 1, n)
{
if (a[i - 1] == a[n - 1] - a[i])
return i;
}
return -1;
}
int main()
{
int n;
while (cin >> n)
{
rep(i, 0, n)
{
cin >> a[i];
if (i != 0)
a[i] += a[i - 1];
}
cout << solve(n) << endl;
}
return 0;
}
M.算式接龙
知识点:DFS
思路:使用stringsteam处理输入,使“±*/”分别用数字31-34表示,注意除数不能为零。。
#include <bits/stdc++.h>
using namespace std;
#define LL long long
#define rep(i, a, b) for (int i = a; i < b; i++)
#define per(i, a, b) for (int i = a; i > b; i--)
#define endl '\n'
const int N = 15;
string sign = "+-*/";
int n, m, k,a[N][N],vis[N][N];
int dir[4][2] = {{1, 0}, {-1, 0}, {0, 1}, {0, -1}};
bool dfs(int x, int y, int p, int ans, int len)
{
if (ans == k)
return true;
rep(i, 0, 4)
{
int tx = x + dir[i][0], ty = y + dir[i][1];
if (tx < 0 || tx >= n || ty < 0 || ty >= m || vis[tx][ty])
continue;
int val = a[tx][ty], t = ans;
vis[tx][ty] = 1;
if (val < 30 && p > 30)
{
if (p == 31)
t += val;
else if (p == 32)
t -= val;
else if (p == 33)
t *= val;
else if (val == 0)
{
vis[tx][ty] = 0;
continue;
}
else
t /= val;
if (dfs(tx, ty, 0, t, len + 1))
return true;
}
if (val > 30 && p < 30)
if (dfs(tx, ty, val, t, len + 1))
return true;
vis[tx][ty] = 0;
}
return false;
}
bool solve()
{
rep(i, 0, n)
{
rep(j, 0, m)
{
if (a[i][j] < 30)
{
vis[i][j] = 1;
if (dfs(i, j, 0, a[i][j], 1))
return true;
vis[i][j] = 0;
}
}
}
return false;
}
int main()
{
stringstream ss;
while (cin >> n >> m)
{
rep(i, 0, n)
{
rep(j, 0, m)
{
string s;
cin >> s;
if (ispunct(s[0]) && s.size() == 1)
{
int k = 0;
for (k = 0; k < 4; k++)
if (s[0] == sign[k])
break;
a[i][j] = 31 + k;
}
else
{
ss.str(s);
ss >> a[i][j];
ss.clear();
}
}
}
cin >> k;
if (solve())
cout << "YES" << endl;
else
cout << "NO" << endl;
}
return 0;
}