长江师范学院第二次校赛
A 观星者
分类考虑四种情况即可
#include<iostream>
using namespace std;
int main(){
int x1,x2,x3,y1,y2,y3;
cin>>x1>>y1>>x2>>y2>>x3>>y3;
int x4,y4;
if(y1==y2) y4=y3;
else if(y1==y3) y4=y2;
else if(y2==y3) y4=y1;
if(x1==x2) x4=x3;
else if(x1==x3) x4=x2;
else if(x2==x3) x4=x1;
cout<<x4<<' '<<y4<<endl;
return 0;
}
B 决胜24点
分类讨论多种情况
#include <iostream>
#include <cmath>
using namespace std;
void solve()
{
double a,b,c;
cin>>a>>b>>c;
if (a+b+c==24)
cout<<"YES"<<endl;
else if (a+abs(b-c)==24||c+abs(a-b)==24||b+abs(c-a)==24)
cout<<"YES"<<endl;
else if (a*b+c==24||a*c+b==24||b*c+a==24)
cout<<"YES"<<endl;
else if (a*b-c==24||a*c-b==24||b*c-a==24)
cout<<"YES"<<endl;
else if (a*b*c==24)
cout<<"YES"<<endl;
else if (a*b/c==24||a*c/b==24||b*c/a==24)
cout<<"YES"<<endl;
else if (a*abs(b-c)==24||c*abs(a-b)==24||b*abs(c-a)==24)
cout<<"YES"<<endl;
else if (a*(b+c)==24||c*(a+b)==24||b*(c+a)==24)
cout<<"YES"<<endl;
else if ((a+b)/c==24||(a+c)/b==24||(b+c)/a==24)
cout<<"YES"<<endl;
else if (a+b/c==24||b+a/c==24||c+a/b==24||a+c/b==24||b+c/a==24||c+b/a==24)
cout<<"YES"<<endl;
else cout<<"NO"<<endl;
}
int main()
{
int n;
cin>>n;
while (n>0)
{
solve();
n--;
}
return 0;
}
C 区间质数和
先用前缀和进行区间和查询的优化,再用除2,3以外,素数可以用6n+-1的规律,来对暴力除法试筛选的时间复杂度进行优化至原本的三分之一
#include <iostream>
#include <cmath>
using namespace std;
const int N = 1e6 + 10;
long long a[N]={0},s[N]={0};
long long n, m,l,r;
bool isPrime(int num) {
if (num==1) return false;
if (num==2||num==3) return true;
if (num%6!=1&&num%6!=5) return false;
int tmp=sqrt(num);
for (int i=5;i<=tmp;i+=6)
if (num%i==0||num%(i+2)==0) return false;
return true;
}
int main()
{
ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
long long ans;
cin>>n>>m;
for (long long i=1;i<=n;i++)
{
cin>>a[i]; s[i]=s[i-1]+a[i];
if(!isPrime(a[i])) s[i]-=a[i];
}
while(m--){
cin>>l>>r;
ans=s[r]-s[l-1];
cout<<ans<<endl;
}
return 0;
}
D 迷宫之主
要求不同位置进入迷宫的最长路径,可以想到用bfs走出所有的最短路径,取最大值
#include <bits/stdc++.h>
using namespace std;
typedef pair<int,int> PII;
int h,w,res=-1e18;
char mp[25][25];
int ds[25][25];
int dx[4]={0,0,1,-1};
int dy[4]={1,-1,0,0};
void bfs(int a,int b){
memset(ds,-1,sizeof ds);
queue<PII> q;q.push({a,b});
ds[a][b]=0;
while(!q.empty()){
PII start=q.front();q.pop();
for(int i=0;i<4;i++){
int x=dx[i]+start.first;int y=dy[i]+start.second;
if(mp[x][y]=='.'&&ds[x][y]==-1){
ds[x][y]=ds[start.first][start.second]+1;
q.push({x,y});
}
}
}
}
int main()
{
ios::sync_with_stdio(0),cin.tie(0);
cin>>h>>w;
for(int i=1;i<=h;i++)for(int j=1;j<=w;j++) cin>>mp[i][j];
for(int i=1;i<=h;i++)for(int j=1;j<=w;j++)
if(mp[i][j]=='.') {
bfs(i,j);
for(int k=1;k<=h;k++)for(int l=1;l<=w;l++)
res=max(res,ds[k][l]);
}
cout<<res<<'\n';
return 0;
}
E 小A在摸鱼!!!
分类讨论,对于第二种有比较巧妙的交换a,b,这样可以少写一次判断
#include <iostream>
#include <algorithm>
using namespace std;
int main()
{
long long int a,b,count=0;
scanf("%lld%lld",&a,&b);
while(a!=b)
{
if (a<b)
{
b=b-a;
count++;
}
swap(a,b);
}
printf("%lld",count);
return 0;
}
F 派蒙的数组
贪心,要使得代价最小,因为正负数都有,所以要让正数足够下,那就让正数的下标取到1,负数直接×当前下标即可
#include <bits/stdc++.h>
using namespace std;
using ll=long long;
const ll N = 1e6+10;
ll a[N]={0};
int main()
{
ll n;
ll sum=0;
cin >> n;
for (ll i = 1;i <= n;i ++)
{
cin >> a[i];
if(a[i]>0)
sum+=a[i];
else
sum+=a[i]*i;
}
cout << sum;
return 0;
}
G 摸鱼时间到
是一道大模拟题,综合比较强,有前缀和,数学和二分查找
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
typedef long long ll;
const int N=2e5+5;
int a[N]; // 存储每个任务的到达时间
vector<int> rest(N); // 存储相邻两个任务之间的时间间隔
vector<ll> sum(N); // 前缀和数组,表示前 i 个时间间隔的总和
int main(){
int n,q;
cin>>n>>q;
for(int i=0;i<n;i++) cin>>a[i];
for(int i=1;i<n;i++) rest[i]=a[i]-a[i-1]; // 计算相邻两个任务之间的时间间隔
sort(rest.begin()+1,rest.begin()+n); // 将时间间隔从小到大排序,为二分查找
for(int i=1;i<n;i++) sum[i]=sum[i-1]+rest[i]; // 计算时间间隔的前缀和数组
while(q--){
int k,p;
cin>>k>>p;
int index=upper_bound(rest.begin()+1,rest.begin()+n,k)-rest.begin(); // 二分查找最后一个时间间隔小于等于 k 的位置
ll tmp=sum[n-1]-sum[index-1]-k*((n-1)-(index-1)); // 计算在该位置之后的任务间隔总和
printf("%s\n",(tmp>=p)?"YES":"NO");
}
return 0;
}
H 简单计数题
三元组,要求下标不相同,元素也不同,三个元素相加为一个目标值,很容易想到暴力,但是会超时,并且不好判重,可以用双指针来做
#include<bits/stdc++.h>
using namespace std;
int main()
{
int n,t;cin>>n>>t;
vector<int>a(n);
for(int i=0;i<n;i++) cin>>a[i];
sort(a.begin(),a.end());
int res=0;
for(int i=0;i<n-2;i++)
{
if(i>0&&a[i]==a[i-1]) continue;
int left=i+1,right=n-1;
while(left<right)
{
int sum=a[i]+a[left]+a[right];
if(sum==t)
{
res++;
while(left<right&&a[left]==a[left+1]) left++;
while(left<right&&a[right]==a[right-1]) right--;
left++;
right--;
}
else if(sum<t) left++;
else right--;
}
}
cout<<res<<'\n';
return 0;
}
I 小A玩篱笆
思维题,要围成一个矩形,首先要考虑是一个偶数,然后再观察是不是四的倍数,如果是四的倍数就会少一种,因为是两两配对,如果出现正方形,那两两配对了两个实际上是一个,所以要减一种
#include <iostream>
using namespace std;
int main()
{
long long int n;
cin>>n;
if (n%2) cout<<"0";
else if (n%4==0)
cout<<n/4-1;
else cout<<n/4;
return 0;
}
J-火星之旅
考点:大模拟
#include<bits/stdc++.h>
using namespace std;
#define IOS ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
const int N = 1e5 + 10;
typedef long long ll;
struct node {
ll v, w; // 终点, 权重
};
struct Graph {
int numv; // 图点的数量
vector<vector<node>> adlist; // 邻接表
vector<ll > dis; // 某个点到某个点的距离
vector<bool > vis; // 标记访问
// 构造函数
Graph(int n) : numv(n), adlist(n + 1), dis(n + 1, 1e14), vis(n + 1, false) {
}
// 向邻接表中添加边和权值
void add(int a, int b, int c) {
adlist[a].push_back({b, c});
}
// 堆优化版dijk
void dijkstra(int s) {
priority_queue<pair<ll, int>, vector<pair<ll, int>>, greater<pair<ll, int >>> q;
dis[s] = 0;
q.push({0, s});
while(q.size()) {
auto it = q.top();
q.pop();
ll u = it.second, d = it.first;
if(vis[u]) {
continue;
}
vis[u] = true;
for(auto &[v, w] : adlist[u]) {
if(dis[v] > d + w) {
dis[v] = d + w;
q.push({dis[v], v});
}
}
}
}
};
struct SegmentTree {
vector<ll > tree;
vector<int > nums;
int numVertices;
SegmentTree(int n) : numVertices(n), tree((n + 1) << 2, 0), nums(n) {}
void push_up(int p) {
tree[p] = min(tree[p << 1], tree[p << 1 | 1]);
}
void add(int i, int x) {
nums[i] = x;
}
void build(int p, int pl, int pr, vector<ll > &dis1, vector<ll > &dis2) {
if (pl == pr) {
tree[p] = dis1[pl] + (dis2[pl] + nums[pl] - 1) / nums[pl];
return;
}
else {
int mid = pl + pr >> 1;
build(p << 1, pl, mid, dis1, dis2);
build(p << 1 | 1, mid + 1, pr, dis1, dis2);
push_up(p);
}
}
void change(int p, int pl, int pr, int k, vector<ll > &dis1, vector<ll > &dis2) {
if (pl == pr) {
tree[p] = dis1[pl] + (dis2[pl] + nums[pl] - 1) / nums[pl];
return ;
}
else {
int mid = pl + pr >> 1;
if (k <= mid) change(p << 1, pl, mid, k, dis1, dis2);
else change(p << 1 | 1, mid + 1, pr, k, dis1, dis2);
push_up(p);
}
}
ll query(int p, int pl, int pr, int l, int r) {
if (l <= pl && pr <= r) return tree[p];
int mid = pl + pr >> 1;
ll v = 0;
if (l <= mid) v = fmin(v, query(p << 1, pl, mid, l, r)) ;
if (r > mid) v = fmin(v, query(p << 1 | 1, mid + 1, pr, l, r)) ;
return v;
}
};
int main() {
IOS;
int n, m, k;
cin >> n >> m >> k;
Graph g(n), neg(n); // 正图和反图, 反图用于计算星际旅游最小价值
for(int i = 1; i <= m; i++) {
int a, b, c, d;
cin >> a >> b >> c >> d;
g.add(a, b, c), neg.add(b, a, d);
}
// 计算出到每个城市需要的货币数量
g.dijkstra(1), neg.dijkstra(n);
SegmentTree sg(N);
for(int i = 1; i <= n; i++) {
int x;
cin >> x;
sg.add(i, x);
}
sg.build(1, 1, n, g.dis, neg.dis);
for(int i = 1; i <= k; i++) {
int k, x;
cin >> k >> x;
sg.add(k, x);
sg.change(1, 1, n, k, g.dis, neg.dis);
cout << sg.query(1, 1, n, 1, n) << "\n";
}
return 0;
}
K-玩游戏
考点:大模拟
#include <bits/stdc++.h>
#define endl "\n"
using namespace std;
constexpr int INF = 0x3f3f3f3f;
constexpr int N = 1e5 + 10;
int n, m, k;
typedef struct T{
int h, a, b, c, d, e, w, g;
}T;
queue<T>A, B;
//小A操作
void move(queue<T> &A, queue<T> &B)
{
T t1 = A.front();
A.pop();
T* t2 = &B.front();
int ww = max(t1.a - t2->c, 0);
int mm = max(t1.b - t2->d, 0);
int z = 0;
if (t1.g >= t1.e) z = t1.w;
if (ww >= z && ww >= mm)//物理攻击
{
++ t1.g;
t2->h = max(0, t2->h - ww);
}else if (mm >= z && mm >= ww)//魔法攻击
{
++ t1.g;
t2->h = max(0, t2->h - mm);
}else if (z >= 0) // 终极技能
{
t2->h = max(0, t2->h - z);
t1.g -= t1.e;
}
A.push(t1);
if (t2->h == 0) B.pop();
}
void solve()
{
if (A.empty() && B.empty())
{
cout << "Draw" << endl;
return ;
}
for (int i = 0; i < k; ++ i)//回合
{
move(A, B);
if (B.empty())//判断B宝可梦数量
{
cout << "Alice" << endl;
// cout << k << endl;//结束在第几回合
return ;
}
move(B, A);
if (A.empty())//判断A宝可梦数量
{
cout << "Bob" << endl;
// cout << k << endl;//结束在第几回合
return ;
}
}
cout << "Draw" << endl;
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(nullptr),cout.tie(nullptr);
cin >> n >> m >> k;
for (int i = 0; i < n; ++ i)
{
T t;
cin >> t.h >> t.a >> t.b >> t.c >> t.d >> t.e >> t.w;
t.g = 0;
A.push(t);
}
for (int i = 0; i < m; ++ i)
{
T t;
cin >> t.h >> t.a >> t.b >> t.c >> t.d >> t.e >> t.w;
t.g = 0;
B.push(t);
}
solve();
return 0;
}