A题
给出n,k,求三个数x/y/z,使得n = x + y + z,并且gcd(x,y) = gcd(x,z) = gcd(y,z) = k
解:在n / k / 3范围内左右查找符合条件的值
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll t,n,k;
int solve()
{
if(n % k) return 0;
ll p = n / k;
ll r = p / 3;
for(ll i = max(2LL,r - 100);i <= min(p,r + 100); ++i)
for(ll j = max(2LL,r - 100);j <= min(p,r + 100); ++j)
{
if(p - i - j <= 1 || __gcd(i,j) != 1 || __gcd(i,p - i - j) != 1 || __gcd(j,p - i - j) != 1) continue;
cout<<i * k<<' '<<j * k<<' '<<(p - i - j) * k<<'\n';
return 1;
}
return 0;
}
int main()
{
std::ios::sync_with_stdio(false);
cin>>t;
while(t--)
{
cin>>n>>k;
if(!solve()) cout<<"-1 -1 -1\n";
}
return 0;
}B题
求分子式的质量
解:栈的基础应用
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 1e5 + 10;
string a;
ll n,ans,k;
stack<ll>s;
void check()
{
if(k)
{
k *= s.top();
s.pop(); s.push(k);
k = 0;
}
}
int main()
{
std::ios::sync_with_stdio(false);
cin>>a; n = a.size();
k = 0;
for(int i = 0;i < n; ++i)
{
if(a[i] == '(') check(),s.push(-1);
else if(a[i] == ')')
{
check();
int sum = 0;
while(!s.empty() && s.top() != -1)
{
sum += s.top();
s.pop();
}
if(!s.empty() && s.top() == -1) s.pop();
if(sum) s.push(sum);
}
else if(a[i] >= '0' && a[i] <= '9') k = k * 10 + a[i] - '0';
else if(a[i] == 'C') check(),s.push(13LL);
else if(a[i] == 'H') check(),s.push(1LL);
else if(a[i] == 'O') check(),s.push(17LL);
}
check();
while(!s.empty()) ans += s.top(),s.pop();
cout<<ans<<'\n';
return 0;
}C题 简单模拟
F题 最后先手必胜
G题
选择(n/2)(向下取整)个才能拿走,并且不能选择在数组中相邻的数,一定要选第x个数,问选出的数的最大的和
解:很显然是DP,必须要选第x个,可以给第x个加上一个很大的数,最后减掉即可。
由于奇数时向下取整会损失精度,所以要分奇偶讨论
奇数:
第i个数字选或者不选
dp[i] = max{dp[i- 1],dp[i - 2] + a[i]}偶数:
第i个数字选或者不选
dp[i] = max{sum[i- 1],dp[i - 2] + a[i]} //如果用dp[i - 1]会少选一个,sum[i - 1]是唯一选法代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll p = 1e16; ///一定要足够大
const int maxn = 2e5 + 10;
ll n,x,a[maxn],dp[maxn],sum[maxn];
int main()
{
std::ios::sync_with_stdio(false);
cin>>n>>x;
for(int i = 1;i <= n; ++i)
cin>>a[i];
a[x] += p;
sum[1] = a[1];
for(int i = 3;i <= n; i += 2)
sum[i] = sum[i - 2] + a[i];
for(int i = 2;i <= n; ++i)
{
if(i % 2) dp[i] = max(dp[i - 1],dp[i - 2] + a[i]);
else dp[i] = max(sum[i - 1],dp[i - 2] + a[i]);
}
cout<<(dp[n] - p)<<'\n';
return 0;
}
I题
构造一个n×m的矩阵,使矩阵中任意相邻的两个数高度差都恰好为1,给出k条信息,说明(xi,yi)这个点的高度为hi。
解:从高度最小的点开始向四个方向bfs即可
#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e5 + 10;
const int ma = 1e9 + 1;
int n,m,k;
vector<int>a[maxn]; ///数组开不下
vector<bool>vis[maxn];
int x,y,h;
int d[4][2] = {{-1,0},{0,-1},{0,1},{1,0}};
struct node
{
int x,y;
int h;
node(int _x,int _y,int _h):x(_x),y(_y),h(_h){}
bool operator<(const node& a) const //注意区分
{
return h > a.h;
}
};
priority_queue<node>q;
bool solve()
{
if(k)
{
while(k--)
{
cin>>x>>y>>h;
if(a[x][y] != -ma && a[x][y] != h)
return 0;
a[x][y] = h;
vis[x][y] = 1;
q.push(node(x,y,h));
}
}
else //k = 0时
{
a[1][1] = 0;
q.push(node(1,1,0)),vis[1][1] = 1;
}
// cout<<q.size()<<endl;
while(!q.empty())
{
node r = q.top();
q.pop();
for(int i = 0;i < 4; ++i)
{
int xx = r.x + d[i][0];
int yy = r.y + d[i][1];
if(xx > n || xx < 1 || yy > m || yy < 1 || vis[xx][yy]) continue;
if(a[xx][yy] != -ma && a[xx][yy] != r.h + 1) return 0;
a[xx][yy] = r.h + 1;
q.push(node(xx,yy,r.h + 1));
vis[xx][yy] = 1;
}
}
for(int i = 1;i <= n; ++i)
for(int j = 1;j <= m; ++j)
for(int kk = 0;kk < 4; ++kk)
{
int xx = i + d[kk][0];
int yy = j + d[kk][1];
if(xx > n || xx < 1 || yy > m || yy < 1) continue;
if(abs(a[i][j] - a[xx][yy]) != 1) return 0;
}
return 1;
}
int main()
{
std::ios::sync_with_stdio(false);
cin>>n>>m>>k;
for(int i = 1;i <= n + 1; ++i)
for(int j = 1;j <= m + 1; ++j)
a[i].push_back(-ma),vis[i].push_back(0);
if(solve())
{
cout<<"Yes\n";
for(int i = 1;i <= n; ++i)
for(int j = 1;j <= m; ++j)
cout<<a[i][j]<<((j == m)?'\n':' ');
}
else cout<<"No\n";
return 0;
}


京公网安备 11010502036488号