哈尔滨理工大学软件与微电子学院程序设计竞赛(同步赛)(A~L) (不含 DEF)

比赛链接
A
在这里插入图片描述
暴力模拟就好了
范围小,直接枚举每一秒,注意坑定在如果A已经超过B距离t了,那么在等待的s秒内不能继续更新为s秒,也就是说,在等待时不要进行距离判定,我这里是用了一个标记变量f来标记是否已经开始等待了

void solve(){
    scanf("%d %d %d %d %d",&v1,&v2,&t,&s,&l);
    int res = 0,p1 = 0, p2 = 0,time=0,f = 0;
    while(1) {
        time ++;
        if(res) {
            res --;
        } else {
            f = 0;
            p1 += v1;
        }
        p2 += v2;
        if(p1 - p2 >= t) {
            if(!f){
                f = 1;
                res = s;
            }
        }
        if(p1 >= l && p2 >= l) {
            printf("Tie %d\n",time);
            return ;
        } else if(p2 >= l) {
            printf("Hong %d\n",time);
            return ;
        } else if(p1 >= l) {
            printf("Ming %d\n",time);
            return;
        }
    }
}

B
在这里插入图片描述
题目不难,只是需要处理很多细节,
我自己的写法是 对于每个数值都加上1e6 然后开一个2e6的vector数组,读入的时候,对于每一种值,都存入对应的下标
要求绝对值最小的话,那么就遍历数组,对于每一个元素a[i],我们就二分查找-a[i]附近的数,因为涉及到不存在的情况,所以我是对于每个数都二分三次,分别找出小于-a[i]中最大的值,大于-a[i]的最小的值,以及-a[i],因为我们在读入的时候,储存了每种数值共有那些下标,所以我们直接在三种大小内从小打到找出第一个下标不等于i的下标,然后更新最小值就可以了

vector<int> v[maxm];
struct node {
    int val, pos;
}arr[maxn];
int n;
bool cmp(node a,node b) {
    if(a.val == b.val) {
        return a.pos < b.pos;
    } else {
        return a.val < b.val;
    }
}
int bin1(int val) {
    int L = 1, R = n, pos = -1;
    while(L <= R) {
        int mid = L + R >> 1;
        if(arr[mid].val > val) {
            pos = mid;
            R = mid - 1;
        } else {
            L = mid + 1;
        }
    }
    return pos;
}
int bin2(int val) {
    int L = 1, R = n, pos = -1;
    while(L <= R) {
        int mid = L + R >> 1;
        if(arr[mid].val < val) {
            pos = mid;
            L = mid + 1;
        } else {
            R = mid - 1;
        }
    }
    return pos;
}
void solve(){
    scanf("%d",&n);
    rep(i,1,n) {
        scanf("%d",&arr[i].val);
        int val = arr[i].val + 1e6;
        v[val].pb(i);
        arr[i].pos = i;
    }
    sort(arr + 1, arr + n + 1, cmp);
    int res = abs(arr[1].val + arr[2].val) , st = arr[1].pos, ed = arr[2].pos;
    rep(i,1,n) {
        //de(i)
        //de(res)
        int tmp = - arr[i].val;
        int pos1 = bin1(tmp);
        //de(pos1)
        int pos2 = bin2(tmp);
       // de(pos1)
        //de(pos2)
        if(pos1 != -1) {
            int val = arr[pos1].val;
            int sz = v[(int)(val + 1e6)].size();
            rep(j,0,sz-1) {
                if(v[(int)(val + 1e6)][j] != arr[i].pos) {
                    int tt = arr[i].val + val;
                    if(abs(tt) < res) {
                        res = abs(tt);
                        st = arr[i].pos;
                        ed = v[(int)(val + 1e6)][j];
                    } else if(abs(tt) == res) {
                        if(arr[i].pos + v[(int)(val + 1e6)][j] < st + ed) {
                            st = arr[i].pos;
                            ed = v[(int)(val + 1e6)][j];
                        }
                    }
                    break;
                }
            }
        }
       // de(res)
        if(pos2 != -1) {
            int val = arr[pos2].val;
            //de(val)
            int sz = v[(int)(val + 1e6)].size();
            rep(j,0,sz-1) {
                if(v[(int)(val + 1e6)][j] != arr[i].pos) {
                    int tt = arr[i].val + val;
                    //de(tt)
                    if(abs(tt) < res) {
                        res = abs(tt);
                        st = arr[i].pos;
                        ed = v[(int)(val + 1e6)][j];
                    } else if(abs(tt) == res) {
                        if(arr[i].pos + v[(int)(val + 1e6)][j] < st + ed) {
                            st = arr[i].pos;
                            ed = v[(int)(val + 1e6)][j];
                        }
                    }
                    break;
                }
            }
        }
       // de(res)
        int vv = tmp + 1e6;
        int sz = v[vv].size();
        rep(j,0,sz-1) {
            if(v[vv][j] != arr[i].pos) {
                int tt = arr[i].val + vv;
                if(abs(tt) < res) {
                    res = abs(tt);
                    st = arr[i].pos;
                    ed = v[vv][j];
                } else if(abs(tt) == res) {
                    if(arr[i].pos + v[vv][j] < st + ed) {
                        st = arr[i].pos;
                        ed = v[vv][j];
                    }
                }
                break;
            }
        }
    }
    printf("%d %d\n",res,st+ed);
}

C
在这里插入图片描述
bfs直接过,搜索入门题…(起点一定不会在高危地区
需要注意的是我们在划高危地区的时候不能把 * 附近都变成 * ,因为这样就会把整个地图都蔓延完,我们应该开一个str二维数组存储地图,然后用一个e二维数组,用1代表不可以走,0代表可以走,之后遍历地图,对于每一个高危点,就在e数组内使得这个点所在的九宫格全变为1,之后记录起点终点,结构体储存坐标与步数,然后对于e数组直接跑一个bfs就可以了

char str[100][100];
int n,m,sx,sy,ex,ey;
int nx[4] = {1,0,-1,0};
int ny[4] = {0,-1,0,1};
int e[100][100],vis[100][100];
void change(int x,int y) {
    e[x][y] = 1;
    rep(i,0,3) {
        e[x+nx[i]][y+ny[i]] = 1;
    }
    e[x-1][y-1]=e[x+1][y+1]=e[x-1][y+1]=e[x+1][y-1]=1;
}
struct node{
    int x,y,s;
};
void bfs() {
    queue<node>que;
    que.push((node){sx,sy,0});
    vis[sx][sy] = 1;
    while(!que.empty()) {
        node now = que.front();
        que.pop();
        int x = now.x, y = now.y, s = now.s;
        if(x == ex && y == ey) {
            printf("%d\n",s);
            return ;
        }
        rep(i,0,3) {
            int tx = x + nx[i], ty = y +ny[i];
            if(tx < 1 || tx > n || ty < 1 || ty > m || e[tx][ty] || vis[tx][ty]) {
                continue;
            }
            vis[tx][ty] = 1;
            que.push((node){tx,ty,s+1});
        }
    }
    puts("Impossible");
}
void solve(){
    ms(e,0),ms(vis,0);
    scanf("%d %d",&n,&m);
    rep(i,1,n) {
        scanf("%s",str[i] + 1);
    }
    rep(i,1,n) {
        rep(j,1,m) {
            if(str[i][j] == '*') {
                change(i,j);
            }
            if(str[i][j] == 'S') {
                sx = i;
                sy = j;
            }
            if(str[i][j] == 'E') {
                ex = i;
                ey = j;
            }
        }
    }
    if(e[ex][ey] == 1) {
        puts("Impossible");
        return ;
    }
    bfs();
}

中间三个题不会写。。
G
在这里插入图片描述
这个简单,因为我们有1到n的所有元素,然后我们可以发现,对于任意n范围的数,我们一定可以变成二进制下每一个数都为1,比如n二进制为 100010,首位一定是1,剩下的每一位都取反 找出的数一定比他小,在他范围内,例如这个就是 011101,异或后就是全为1了,所以我们只需要求出n二进制下共有多少位,然后每一位都变成1就可以了
如果n的二进制本身就全为1,比如1111,那我们只需要用n-1来和1异或就可以了,这样求出来的也是全为1,
注意特判1,1只能和1自己,所以为0
这题似乎不需要开unsigned long long…我开了,然后没注意把int给爆了,,

uLL cal(uLL x) {
    uLL res = 0;
    while(x) {
        x >>= 1;
        res ++;
    }
    return res;
}
void solve(){
    uLL n;
    cin >> n;
    if(n == 1){
        cout << 0 << endl;
        return ;
    }
    cout << qpow((uLL)(2),cal(n)) - (uLL)(1) << endl;
}

H
在这里插入图片描述
并查集 or BFS ?
我写的并查集,我看有人用bfs也过了,应该都可以吧,
常规并查集,只是多加一个hei(高度)的属性,代表这个集合内元素的总个数,然后对于每个点,如果它周围有和自己不一样的符号的点,就合并(每个点可以重复走),合并的时候注意一下高度的合并就可以了
我们可以用一个pos二维数组,对于每一个点进行位置标记,然后对于每个点,用pos[i][j]就可以代表这个点了
合并高度

int fa = seek(pos[x][y]), fb = seek(pos[tx][ty]);
        if(fa != fb) {
            dad[fa] = fb;
            hei[fb] += hei[fa];
        }

全部代码是

int n,m,q;
int pos[maxn][maxn];
char str[maxn][maxn];
int dad[maxn  * maxn], hei[maxn * maxn];
int nx[4] = {0,1,0,-1};
int ny[4] = {1,0,-1,0};
int seek(int x) {
    return x == dad[x] ? x : dad[x] = seek(dad[x]);
}
void change(int x,int y) {
    rep(i,0,3) {
        int tx = x + nx[i], ty = y + ny[i];
        if(tx < 1 || tx > n || ty < 1 || ty > m) {
            continue;
        }
        if(str[x][y] == str[tx][ty]) {
            continue;
        }
        int fa = seek(pos[x][y]), fb = seek(pos[tx][ty]);
        if(fa != fb) {
            dad[fa] = fb;
            hei[fb] += hei[fa];
        }
    }
}
void solve(){
    scanf("%d %d %d",&n,&m,&q);
    rep(i,1,n) {
        //rep(j,1,m) {
            scanf("%s",str[i] + 1);
        //}
    }
    int tot = 0;
    rep(i,1,n) {
        rep(j,1,m) {
            pos[i][j] = ++ tot;
        }
    }
    rep(i,1,tot) {
        dad[i] = i;
        hei[i] = 1;
    }
    rep(i,1,n) {
        rep(j,1,m) {
            change(i,j);
        }
    }
    while(q --) {
        int a,b;
        scanf("%d %d",&a,&b);
        int f = seek(pos[a][b]);
        printf("%d\n",hei[f]);
    }
}

I
在这里插入图片描述
这个,就是一个欧拉筛,筛出来素数之后再记录一个前缀和,然后直接O1查询了

int prime[maxn];
int sum[maxn];
void ESS(){
    int n = 1e7;
    for(int i = 0;i <= n;i++){
		prime[i] = 1;
        sum[i] = 0;
    }
    int cup[maxn],cnt=0;
    for(int i = 2;i <= n;i++){
		if(prime[i]){
			cup[++ cnt] = i;
        }
        for(int j = 1;j <= cnt && i*cup[j] <= n; ++ j){
			prime[i * cup[j]] = 0;
            if(i % cup[j] == 0){
                break;
            }
        }
    }
    prime[0] = prime[1] = 0;
    sum[0] = sum[1] = 0;
    rep(i,1,n) {
        if(prime[i]) {
            sum[i] ++;
        }
        sum[i] += sum[i-1];
    }
}
void solve(){
    int a = read(), b = read();
    printf("%d\n",sum[b] - sum[a-1]);
}

可恶啊,这个I没抢到一血。。我直接点开这个。。手速过去,然后是第二个写出来的,,就差一点
J
在这里插入图片描述
签到题,先比较长度,长度相同遍历找出第一个差异的地方
当然,我是python过的,python大法好

a = int(input())
b = int(input())
if a > b :
    print('>')
elif a < b :
    print('<')
else :
    print('=')

K
在这里插入图片描述
组合数学简单题,高中排列组合简单题,会逆元就能写
步数最少,那就是只能向右向下咯,所以我们需要n-1次向下,m-1次向右,所以就是再总的n-1+m-1次走路选择中,找出n-1次来向下走就可以了,所以就是组合数 C n + m 2 n 1 C_{n+m-2}^{n-1} ,so直接打个逆元表就过了
附上逆元解法
a / b a/b 取模 m o d mod 就是a乘于b的逆元,b的逆元求法是 inv(b) = mqpow(b,mod-2,mod),所以加一个快速幂就过啦
附上组合数求法
C n m = n ! / ( m ! ( n m ) ! ) C_{n}^{m} = n!/(m!*(n-m)!)

ll fact[maxn];
void init(){
    ll n = 2e6;
    fact[0] = 1;
    for(ll i = 1;i <= n;i++){
		fact[i] = (fact[i-1] * i)%mod;
    }
}
ll inv(ll x,ll mo){
	return mqpow(x,mo-2,mo);
}
ll cal(ll n,ll m,ll mo){
	return (fact[n] * inv(fact[m],mo)%mo * inv(fact[n-m],mo)%mo)%mo;
}
void solve(){
    ll n,m;
    cin >> n >> m;
    n--;
    m--;
    cout << cal(n+m,n,mod) << endl;
}

L
在这里插入图片描述
这个其实就是一个考察二分的题目,先sort,然后对于每一个元素作为最小值,二分找出第一个大于a[i]+5的下标,然后减一,起点与终点就是人数,找出最大人数就可以了

LL arr[maxn],n;
void solve(){
    scanf("%lld",&n);
    rep(i,1,n) {
        scanf("%lld",&arr[i]);
    }
    sort(arr + 1,arr + n + 1);
    LL res = 1;
    rep(i,1,n) {
        LL tmp = arr[i] + 5;
        if(tmp > arr[n]) {
            LL dis = n - i + 1;
            res = max(res, dis);
        } else {
            int pos = upper_bound(arr + 1, arr + n + 1, tmp) - arr;
            pos --;
            res = max((LL)(pos - i + 1), res);
        }
    }
    printf("%lld\n",res);
}

猜你喜欢

转载自blog.csdn.net/leoxe/article/details/106749651
今日推荐