这次比赛怎么追都追不上,然后发现泄题了,好离谱啊!
A
模拟即可
#include<bits/stdc++.h>
using namespace std;
int n;
bool solve()
{
cin >> n;
string s1, s2;
cin >> s1 >> s2;
for(int i = 0; i < n; i ++) if(s1[i] + s2[i] == '1' + '1') return false;
return true;
}
int main()
{
int T;
cin >> T;
while(T --) if(solve()) cout << "YES\n"; else cout << "NO\n";
}
B
暴力
用cnt1,cnt2两个数组去记录,然后枚举各种可能结果,(1,2),(1,3)这样
成功的等价条件是,存在
if(j != i && cnt2[j] + min(cnt1[j], cnt1[i] - n / 2) >= n / 2)
解释一下就是首先i和j不能相同,举个例子,含有1的有5组,其中有2组含有2,不含有1但是含有2的有3组,一共8组,那我就可以从含有1的5组中拿出1组给2,然后就有4组含有1,和4组含有2,需要判断的是,我可以从1中拿出多少组呢,首先要保证我有那么多2,其次要保证拿出来之后,我剩下的1还够用,我至少要剩下n/2个1的!
#include<bits/stdc++.h>
using namespace std;
int n;
bool solve()
{
cin >> n;
vector<vector<int>> a(n);
for(int i = 0; i < n; i ++)
{
a[i] = vector<int> (5, 0);
for(int j = 0; j < 5; j ++) cin >> a[i][j];
}
for(int i = 0; i < 5; i ++)
{
int cnt1[5] = {0}, cnt2[5] = {0};
for(int j = 0; j < n; j ++)
if(a[j][i])
for(int k = 0; k < 5; k ++) cnt1[k] += a[j][k];
else for(int k = 0; k < 5; k ++) cnt2[k] += a[j][k];
if(cnt1[i] < n / 2) continue;
for(int j = 0; j < 5; j ++)
if(j != i && cnt2[j] + min(cnt1[j], cnt1[i] - n / 2) >= n / 2) return true;
}
return false;
}
int main()
{
int T;
cin >> T;
while(T --) if(solve()) cout << "YES\n"; else cout << "NO\n";
}
C
C题写了long double,然后觉得精度不够,灵机一动写long long2333
a和b可以一起消掉等价于(a + b) / 2 * n = total
用个map去存方便找数就过了
#include<bits/stdc++.h>
using namespace std;
using ll = long long;
void solve()
{
ll s = 0, n, res = 0;
cin >> n;
vector<ll> a(n);
for(int i = 0; i < n; i ++) cin >> a[i], s += a[i];
if(!(s * 2 % n))
{
map<ll, ll> cnt;
for(auto x : a) cnt[x] ++;
for(auto x : cnt)
if(x.first * n == s) res += x.second * (x.second - 1);
else if(cnt.count(s * 2 / n - x.first))
res += x.second * cnt[s * 2 / n - x.first];
}
cout << res / 2 << endl;
}
int main()
{
int T;
cin >> T;
while(T --) solve();
}
D
就是组合问题,首先算C(n,3),然后减掉不合理的部分
首先我们知道不会出现两个(a, b),即a相同时b一定不同,反过来也是
所以如果一个组中三个a相同,那它合理,如果三个a各不相同,那也合理
不合理的只有一种就是(a, b), (a, c), ((d, b)或(d, c))
所以我们统计一下两个数组各个数各有多少,然后我们遍历从1到n
包含(a, b) 的有(v1中a的个数-1)*(v2中b的个数-1)个,累加即可
我用an数组因为他有说ai<=n,不然就用map也可以,应该不会T
有趣的是,这道题泄题的答案里面没有整成ll,然后出现大量抄题解然后被hack的情况,所以大家可以上号看看排名又前进了多少2333
#include<bits/stdc++.h>
using namespace std;
using ll = long long;
void solve()
{
ll res = 0, n;
cin >> n;
vector<ll> a(n), b(n), an(n), bn(n);
for(int i = 0; i < n; i ++) cin >> a[i] >> b[i], an[--a[i]] ++, bn[--b[i]] ++;
res = n * (n - 1) * (n - 2) / 6;
for(int i = 0; i < n; i ++) res -= (an[a[i]] - 1ll) * (bn[b[i]] - 1ll);
cout << res << endl;
}
int main()
{
int T;
cin >> T;
while(T --) solve();
}
E
E我的做法也是模拟,虽然整个图是1000*1000,但是我想了想,每次只改变一个块的话,我只搜索看看我这个块lock上和unlock的时候对结果的影响,如果unlock就加上,lock就减去,时间复杂度倒也不高,因为是模拟,所以代码写的就很长,凑合看hhh
#include<bits/stdc++.h>
using namespace std;
using ll = long long;
const int N = 1117;
ll tot = 0, n, m, g[N][N], q;
void update()
{
int x, y;
cin >> x >> y;
int r1 = 1, r2 = 1, c1 = 1, c2 = 1;
for(int i = 1; ; i ++)
if(x + i <= n && y + i - 1 <= m && !g[x + i][y + i - 1])
{
r1 ++;
if(y + i <= m && !g[x + i][y + i]) r1 ++;
else break;
} else break;
for(int i = 1; ; i ++)
if(y - i && x - i + 1 && !g[x - i + 1][y - i])
{
r2 ++;
if(x - i && !g[x - i][y - i]) r2 ++;
else break;
} else break;
for(int i = 1; ; i ++)
if(x + i - 1 <= n && y + i <= m && !g[x + i - 1][y + i])
{
c1 ++;
if(x + i <= n && !g[x + i][y + i]) c1 ++;
else break;
} else break;
for(int i = 1; ; i ++)
if(x - i && y - i + 1 && !g[x - i][y - i + 1])
{
c2 ++;
if(y - i && !g[x - i][y - i]) c2 ++;
else break;
} else break;
if(g[x][y]) g[x][y] = 0, tot += 1ll * r1 * r2 + 1ll * c1 * c2 - 1;
else g[x][y] = 1, tot -= 1ll * r1 * r2 + 1ll * c1 * c2 - 1;
cout << tot << endl;
}
void solve()
{
cin >> n >> m >> q;
tot = n * m;
for(int i = 2; i <= min(m, n) + 1; i ++)
tot += (m - i + 1) * (n - i + 2) + (n - i + 1) * (m - i + 2)
+ (m - i + 1) * (n - i + 1) * 2;
while(q --) update();
}
int main()
{
int T;
T = 1;
while(T --) solve();
}
大佬是清华的吗?