A.伊甸之花
分析:若乐曲中同时存在1和m则无解,否则一定可以通过整体上移/下移一个音调来满足
#include<bits/stdc++.h>
using namespace std;
int n,m,f1,f2;
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cin>>n>>m;
for(int i=1;i<=n;i++)
{
int x;
cin>>x;
if(x==1) f1=1;
if(x==m) f2=1;
}
if(f1&&f2) cout<<"No"<<endl;
else cout<<"Yes"<<endl;
return 0;
}
B.显生之宙
分析:根据题意,设想一下要让结果最小,应该如何操作。很显然对于负数,把其他所有数都加上这个数,对于正数,只选择一个数增加。
然后为了让负数最大化利用,将数组从小到大排序,让最小的数放前面,就可以尽可能让更多的数加上这个负数。然后就是模拟前面说的这个操作的过程。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=5e5+10;
int n;
ll a[N];
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
int T;
cin>>T;
while(T--)
{
int n;
cin>>n;
for(int i=1;i<=n;i++) cin>>a[i];
sort(a+1,a+1+n);
ll sum=0,ans=0;//sum记录需要减的负数之和
for(int i=1;i<n;i++)
{
a[i]+=sum;
if(a[i]>=0) ans+=a[i];
else sum+=a[i];
}
cout<<ans+a[n]+sum<<endl;
}
return 0;
}
C.太阳之华
分析:观察样例,直接猜以下结论:开始全都是蓝,则直接后手赢,如果红能一步赢,则先手赢,否则肯定会僵持住,就是平局。(证明不来)
####红赢<---->红先手一步就能赢(因为红先下棋,红色+1,然后蓝下棋,蓝+1,如果红先手不能一步赢蓝,则会一直循环下去,即为平局)
所以这题主要代码考察如何判断红色一步直接赢,我的想法是这样:
用并查集把所有红色的连通块都缩在一起,统计选择每个连通块,能够增加的蓝色方块个数,若某个连通块该值等于场上所有蓝色方块个数,则可以一步先手赢。
#include<bits/stdc++.h>
using namespace std;
int n,m,T;
char s[2010][2010];
set<int> st;
bool vis[2010][2010];//判断该格子有没有被遍历过
void dfs(int x,int y)
{
if(vis[x][y]) return;
vis[x][y]=true;
int dx[4]={0,1,0,-1},dy[4]={1,0,-1,0};
for(int d=0;d<=3;d++)
{
int nx=x+dx[d],ny=y+dy[d];
if(nx>0&&nx<=n&&ny>0&&ny<=m)
{
if(s[nx][ny]=='#') dfs(nx,ny);
else st.insert(nx*2020+ny);//将所有的红色格子进行编码存储到set中
}
}
}
int main()
{
cin>>T;
while(T--)
{
cin>>n>>m;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
cin>>s[i][j];
int blue=0;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
if(s[i][j]=='.') blue++;
int win=0;
memset(vis,false,sizeof vis);//每一次操作前初始化
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
{
if(s[i][j]=='#'&&vis[i][j]==false)
{
st.clear();//每一次操作前初始化
dfs(i,j);
if(st.size()==blue) win=1;
}
}
if(blue==n*m) cout<<"Blue"<<endl;
else if(!win) cout<<"Draw"<<endl;
else cout<<"Red"<<endl;
}
return 0;
}
D.冥古之潮
分析:1.以 x 为起点,bfs一遍图,处理出来数组 cnt[i] 表示距离 x 为 i 的结点的数量(因为题目中dis[i]为最短距离,因此用BFS搜索)
2.
#include <bits/stdc++.h>
typedef long long ll;//记得开long long
using namespace std;
const int maxn = 1e6 + 10;
const int maxm = 5e3+10;
const int mod = 1e9 + 7;
vector<ll> g[maxn];//用邻接矩阵存图
ll dep[maxn], d[maxn], vis[maxn];
ll dp[maxm][maxm];
ll n, m, q, x;
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cin >> n >> m >> q >> x;
for (int i = 1; i <= m; i++)
{
int u, v;
cin>>u>>v;
g[u].push_back(v);//用邻接矩阵存图
g[v].push_back(u);
}
queue<int> qu;
qu.push(x);
vis[x] = 1;
while (!qu.empty())//bfs一遍图
{
int u = qu.front();
qu.pop();
for (auto t : g[u])
{
if (vis[t])
continue;
vis[t] = 1;
dep[t] = dep[u] + 1;
d[dep[t]]++;
qu.push(t);
}
}
dp[0][0] = 1;
for (int i = 1; i <= 5000; i++)
{
for (int k = 0; k <= 5000; k++)
{
dp[i][k] = dp[i - 1][k];//不选第i个点,直接转移
if (k)//选第i个点
dp[i][k] = dp[i][k] + dp[i - 1][k - 1] * d[i];
dp[i][k] %= mod;
}
}
while (q--)
{
int k;
cin >> k;
cout << dp[5000][k] << endl;
}
return 0;
}