[哈理工程序竞赛]题解

哈理工

A race

签到题 直接模拟,最大时间就是L/v2

#include <bits/stdc++.h>
using namespace std;
int main()
{
    int v1,v2,t,s,L;
    cin>>v1>>v2>>t>>s>>L;
    int hong=L/v2;
    int hpos=0,mpos=0;
    for(int i=0;i<hong;){
        if(mpos-hpos>=t){
            hpos+=s*v2;
            i+=s;
        }else {
            hpos+=v2;
            mpos+=v1;
            ++i;
        }
        if(mpos>=L&&hpos<L) {cout<<"Ming "<<min(i,hong);break;}
        else if(mpos>=L&&hpos>=L) {cout<<"Tie "<<min(i,hong);break;}
        else if(mpos<L&&hpos>=L) {cout<<"Hong "<<min(i,hong);break;}
    }
    return 0;
}

B 排序

要求abs(a[i]+a[j])最小且i+j最小,那么按abs(val)直接排序,存储每个数第一次出现的index
然后扫描一遍 最小值就是

#include <bits/stdc++.h>
using namespace std;

struct Data {
    int val, index; //存值和索引
} a[100001];

unordered_map<int, int> v;

bool flag1 = false, flag2 = false;

bool cmp(Data x, Data y) {
    if (abs(x.val) == abs(y.val)) {
        return x.index < y.index;
    }
    return abs(x.val) < abs(y.val);
}

int main() {
    int n;
    cin >> n;
    for (int i = 0; i < n; i++) {
        cin >> a[i].val;
        if (a[i].val > 0) flag1 = true;
        else if (a[i].val < 0) flag2 = true;
        a[i].index = i + 1;
        if (v.find(a[i].val) == v.end()) { //存储第一次出现的位置
            v[a[i].val] = i + 1;
        }
    }
    sort(a, a + n, cmp);
    if (!flag2) { // 不存在小于0的数
        cout << abs(a[0].val + a[1].val) << " " << a[0].index + a[1].index << endl;
    } else if (!flag1) {
        cout << abs(a[0].val + a[1].val) << " " << a[0].index + a[1].index << endl;
    } else {
        int mmin = 1 << 30;
        int idxSum = 0;
        for (int i = 1; i < n; i++) {
            if (abs(a[i].val + a[i - 1].val) < mmin) {
                mmin = abs(a[i].val + a[i - 1].val);
                //idxSum = a[i].index+a[i-1].index;
                idxSum = v[a[i].val] + v[a[i - 1].val];
            } else if (abs(a[i].val + a[i - 1].val) == mmin) {
                idxSum = min(idxSum, v[a[i].val] + v[a[i - 1].val]);
                //idxSum = min(idxSum,a[i].index+a[i-1].index);
            }
        }
        cout << mmin << " " << idxSum << endl;
    }
    return 0;
}

C bfs

bfs板子题

#include <bits/stdc++.h>
using namespace std;
#define mem(a,b) memset(a,b,sizeof(a))
#define pii pair<int,int>
#define int long long
#define ll __int128_t
const int inf = 0x3f3f3f3f;
const int maxn = 60;
const int M = 1e9+7;
int n,m,k,ok;

char a[maxn][maxn];

bool judge(int x,int y)
{
    for(int i = -1; i <= 1; i++)
    {
        for(int j = -1; j <= 1; j++)
        {
            if(a[x+i][y+j] == '*') return true;
        }
    }
    return false;
}

struct node
{
    int x,y,z;
    node(){}
    node(int a,int b,int c) {
        x = a,y = b,z = c;
    }
};

int to[4][2] = {0,1,1,0,0,-1,-1,0};

bool vis[maxn][maxn];

int bfs(int x,int y)
{
    queue<node> q;
    q.push(node(x,y,0));
    vis[x][y] = 1;
    while(!q.empty())
    {
        x = q.front().x;
        y = q.front().y;
        int z = q.front().z;
        q.pop();
        if(judge(x,y)) continue;
        if(a[x][y] == 'S') return z;
        for(int i = 0; i < 4; i++)
        {
            int xx = x + to[i][0];
            int yy = y + to[i][1];
            if(xx <= 0 || yy <= 0 || xx > n || yy > m) continue;
            if(judge(xx,yy) || vis[xx][yy]) continue;
            vis[xx][yy] = 1;
            q.push(node(xx,yy,z+1));
        }
    }
    return -1;
}


signed main()
{
#ifdef ONLINE_JUDGE
#else
    freopen("data.in", "r", stdin);
#endif
    cin>>n>>m;
    for(int i = 1; i <= n; i++)
    {
        cin>>(a[i]+1);
    }
    for(int i = 1; i <= n; i++)
    {
        for(int j = 1; j <= m; j++)
        {
            if(a[i][j] == 'E')
            {  
                int ans = bfs(i,j);
                if(ans == -1)
                {
                    puts("Impossible");
                }
                else
                {
                    cout<<ans<<endl;
                }

            }
        }
    }
    return 0;
}

K 快速幂 逆元

因为是最短路,所以只能往右或者往下走,从(1,1)走到(x,y)点选x-1步下 y-1步右
所以答案为C(x-1+y-1,x-1),因为数很大 所以利用逆元(快速幂求法)

#include <bits/stdc++.h>
using namespace std;
#define ll long long
const ll MAN = 2e6 + 1;
const ll MOD = 1e9+7;
const ll p = 1e9+7;
// ax=1(mod b) 费马小定理ax=a^b-1(mod b)  x=a^b-2(mod b)
ll qpow(long long a, long long b)
{
    ll ans = 1;
    //a = (a % p + p) % p;
    while(b) {
        if (b & 1) ans = (a * ans) % p;
        a = (a * a) % p;
        b>>=1;
    }
    return ans;
}
ll ff[MAN];
ll rff[MAN]; // n!的逆元
ll Combination(ll x,ll y){
    return (ff[x]*rff[x-y]%MOD)*rff[y]%MOD;
}

int main(){
    int t;cin>>t;
    ff[0]=1;rff[0]=1;
    for(int i=1; i<=MAN; i++) {//预计算n!
        ff[i]=(ff[i-1]*i)%MOD;
        rff[i]=qpow(ff[i],MOD-2);
    }
    while(t--){
        ll x,y;cin>>x>>y;
        cout<<Combination(x-1+y-1,x-1)<<endl;
    }
    return 0;
}

G:XoR

找出最大值N的最高位,然后所有位都变为1就是最大值(可以试一下,总能凑出来)

//找出最大值N的最高位,然后所有位都变为1就是最大值
#include<bits/stdc++.h>
#define N 100005
using namespace std;

int main()
{
    long long n;cin>>n;
    if(n==1) cout<<0;
    else{
        int num=0;
        while(n){
            num++;
            n>>=1;
        }
        cout<<(long long)((1LL<<num)-1);
    }
    return 0;
}

H maze

dfs,从某个点能到多少个点,想象成一个并查集,集合里面所有点能到的点的数目都是集合内点的总数。

#include <bits/stdc++.h>
using namespace std;
int n, m, q;
char maze[3005][3005];
typedef pair<int, int> P;
queue<P> que;
int vis[3005][3005];
int dx[4] = {0, 0, 1, -1}, dy[4] = {1, -1, 0, 0};
int pointTol = 0;

bool judge(int x, int y) {
    if (x >= 0 && x < n && y >= 0 && y < m && !vis[x][y]) {
        return true;
    }
    return false;
}

void dfs(int x, int y) {
    int tx, ty;
    for (int i = 0; i < 4; i++) {
        tx = x + dx[i], ty = y + dy[i];
        if (judge(tx, ty) && maze[x][y] != maze[tx][ty]) {
            pointTol++;
            vis[tx][ty] = 1;
            que.push({tx, ty});
            dfs(tx, ty);
        }
    }
    return ;
}

int main() {
    cin >> n >> m >> q;
    for (int i = 0; i < n; i++) {
        cin >> maze[i];
    }
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < m; j++) {
            if (!vis[i][j]) {
                que.push({i, j});
                vis[i][j] = 1;
                pointTol = 1;
                dfs(i, j);
                while (!que.empty()) {
                    vis[que.front().first][que.front().second] = pointTol;
                    que.pop();
                }
            }
        }
    }
    int x, y;
    while (q--) {
        cin >> x >> y;
        cout << vis[x - 1][y - 1] << endl;
    }
    return 0;
}

D

难题,异或和为x,和为y;求选出的数组最小个数
选几个例子可以推到x<=y 且x和y的奇偶性相同;
如果x=y显然只需要一个数就可以了
如果 要知道有个性质就是若x&a==0,则(x+a)^a=x^a^a=x
如果 是不是只需要两个数(x,x+a) 如果不满足x&a=0,就只能是(x,a,a)三个数

#include <bits/stdc++.h>
using namespace std;
int main()
{
    int x,y;
    while(~scanf("%d %d",&x,&y)){
        if(x==0&&y==0) {
            cout<<0;
        }
        else if((x&1) != (y&1)) cout <<-1;
        else if(x==y) cout<<1;
        else if(x>y){
            cout<<-1;
        }else{
            int a=(y-x)/2;
            if((x&a)==0) cout<<2;
            else cout<<3;
        }
        cout<<endl;
    }
}

L

签到题 排序,枚举每个数a[i] 二分找到第一个大于等于a[i]+5的位置即可

#include <bits/stdc++.h>
using namespace std;
#define ll long long
const int N=2e5+2;
ll a[N];
int main(){
    int n;cin>>n;
    for(int i=0;i<n;++i){
        cin>>a[i];
    }
    sort(a,a+n);
    ll ans=0;
    for(int i=0;i<n;++i){
        ll x=upper_bound(a,a+n,a[i]+5)-a-i;
        ans=max(ans,x);
    }
    cout<<ans;
    return 0;
}

J

签到题,直接字符串比较大小即可

#include <bits/stdc++.h>
using namespace std;
int main(){
    string s1,s2;
    cin>>s1>>s2;
    if(s1.size()>s2.size()){
        cout<<">";return 0;
    }else if(s1.size()<s2.size()){
        cout<<"<";return 0;
    }
    if(s1.compare(s2)==0){
        cout<<"=";
    }else if(s1.compare(s2)>0){
        cout<<">";
    }else{
        cout<<"<";
    }
    return 0;
}
全部评论

相关推荐

10-17 12:16
同济大学 Java
7182oat:快快放弃了然后发给我,然后让我也泡他七天最后再拒掉,狠狠羞辱他一把😋
点赞 评论 收藏
分享
点赞 收藏 评论
分享
牛客网
牛客企业服务