A. Zoning Restrictions Again
分析:根据题意简单模拟一下就可以了。
#include "bits/stdc++.h"
using namespace std;
int a[54];
int main() {
int n, m, h;
cin >> n >> h >> m;
int l, r, x;
for (int i = 0; i <= n; ++i) {
a[i] = h;
}
while (m--) {
cin >> l >> r >> x;
for (int i = l; i <= r; ++i) {
a[i] = min(x, a[i]);
}
}
long long ans = 0;
for (int i = 1; i <= n; ++i) {
ans += a[i] * a[i];
}
cout << ans << endl;
}
B. Double Matrix
分析:显而易见的,把每个位置较小的数放在第一个mat里面,较大的放在第二个mat里面,这样是最优的,然后再判断一下就可以了。
#include "bits/stdc++.h"
using namespace std;
int a[54][54], b[54][54];
int main() {
int n,m;
cin >> n>>m;
for (int i = 1; i <= n; ++i) {
for (int j = 1; j <= m; ++j) {
scanf("%d", &a[i][j]);
}
}
for (int i = 1; i <= n; ++i) {
for (int j = 1; j <= m; ++j) {
scanf("%d", &b[i][j]);
if (a[i][j] > b[i][j])swap(a[i][j], b[i][j]);
}
}
/*for (int i = 1; i <= n; ++i) {
for (int j = 1; j <= n; ++j) {
printf("%d ",a[i][j]);
}
puts("");
}
for (int i = 1; i <= n; ++i) {
for (int j = 1; j <= n; ++j) {
printf("%d ",b[i][j]);
}
puts("");
}*/
bool ok = 1;
for (int i = 1; i <= n; ++i) {
for (int j = 2; j <= m; ++j) {
if (a[i][j] <= a[i][j - 1])ok = 0;
if (b[i][j] <= b[i][j - 1])ok = 0;
}
}
for (int j = 1; j <= m; ++j) {
for (int i = 2; i <= n; ++i) {
if (a[i][j] <= a[i-1][j])ok = 0;
if (b[i][j] <= b[i-1][j])ok = 0;
}
}
if(ok)puts("Possible");
else puts("Impossible");
}
C. Hide and Seek
分析:如果k=0,那么ans = 3*n-2。当k!=0时,减掉数组的长度位2的子序列出现过的情况就可以了。
#include "bits/stdc++.h"
using namespace std;
const int mod = 1e9+7;
struct node
{
int x,y;
bool friend operator < (node a,node b){
return a.x==b.x?a.y<b.y:a.x<b.x;
}
bool friend operator == (node a,node b){
return a.x==b.x&&a.y==b.y;
}
};
int main(){
int n,k;
cin>>n>>k;
int ans = 3*n - 2;
int x;
unordered_map<int,int>mp;
map<node,bool>mp2;
for (int i = 0; i < k; ++i) {
cin>> x;
if(mp2.count({x+1,x})== 0&& mp.count(x+1)){
mp2[{x+1,x}]=1;
ans--;
}
if(!mp2.count({x-1,x}) && mp.count(x-1)){
mp2[{x-1,x}]=1;
ans--;
}
mp[x]++;
}
cout<<ans - mp.size()<<endl;
}
D. Chladni Figure
分析:首先,转动n个点必然重合,若存在小于n的答案,那么一定是n的因子,且小于等于n/2。
那么直接枚举n的因子,然后暴力判断是否重合就可以了。
#include "bits/stdc++.h"
using namespace std;
const int mod = 1e9 + 7;
vector<pair<int, int>> v;
map<pair<int,int>,bool>mp;
int main() {
int n, m;
cin >> n >> m;
int A, B;
for (int i = 0; i < m; ++i) {
scanf("%d%d", &A, &B);
if (A > B)swap(A, B);
v.push_back(make_pair(A, B));
mp[make_pair(A,B)]=1;
/*if (B - A <= n / 2) {
v.push_back(make_pair(A, B));
mp[make_pair(A,B)]=1;
}
else{
v.push_back(make_pair(B, A));
mp[make_pair(B,A)]=1;
}*/
}
sort(v.begin(),v.end());
bool ok = 0;
bool yes = 0;
pair<int,int>t;
for (int i = 1; i <= n/2 && !yes; ++i) {
if(n%i)continue;
ok=1;
for (int j = 0; j < v.size() && ok; ++j) {
t = v[j];
t.first+=i;
t.second+=i;
t.first%=n;
t.second%=n;
if(t.first==0)t.first=n;
if(t.second==0)t.second=n;
if(t.first>t.second)swap(t.first,t.second);
if(mp.count(t))continue;
else ok = 0;
}
if(ok)yes = 1;
}
if(yes)puts("Yes");
else puts("No");
}
E. Thanos Nim
分析:首先朴素的想,当轮到某个人的时候,这个人一定不能率先把某一对拿到0,因为下轮的人只需要拿n/2个0就赢了。
那么也不能率先拿到1(意思是拿完之后不能有<=n/2个1,大于是可以的),因为这样下轮的人只需要拿n/2个1,那么在下轮必定会拿出一个以上的0(因为此时1的个数>n/2)。
那么策略就出来了,如果此时有大于等于n/2个数严格大于最小值,那么我就将这n/2个数拿到当前的最小值。那么下轮的人必定会减少这个最小值,只需要重复操作就可以了,最后必定是后手的人先把某堆拿到0,这样就赢了。
所以简单判断一下是否存在大于等于n/2个数严格大于最小值就可以了。
#include "bits/stdc++.h"
using namespace std;
const int mod = 1e9 + 7;
int a[54];
int main() {
int n;
cin>>n;
int mini = 100;
for (int i = 0; i < n; ++i) {
scanf("%d",&a[i]);
mini = min(mini,a[i]);
}
int cnt = 0;
for (int i = 0; i < n; ++i) {
if(a[i]>mini)cnt++;
}
if(cnt>=n/2)puts("Alice");
else
puts("Bob");
return 0;
}