哈爾濱理工大學軟件與微電子學院程序設計競賽題解

題目鏈接

A.Race

題意:
v1,v2t小紅和小明賽跑,速度分別爲v1,v2,如果小明在某個整數秒超過小紅t米及以上
sl就停下來休息s秒,賽道長總共l米,問誰會贏
題解:
l<=10000,lv1,v2l<=10000,並且l是v1,v2的公倍數
t所以直接模擬每秒,如果他倆距離大於等於t
就讓小明停止
看他倆誰先到終點或者同時到達
AC代碼

/*
    Author:zzugzx
    Lang:C++
    Blog:blog.csdn.net/qq_43756519
*/
#include<bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define pb push_back
#define mp make_pair
#define all(x) (x).begin(),(x).end()
#define endl '\n'
#define SZ(x) (int)x.size()
typedef long long ll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
const int mod=1e9+7;
//const int mod=998244353;
const double eps = 1e-10;
const double pi=acos(-1.0);
const int maxn=1e6+10;
const ll inf=0x3f3f3f3f;
const int dir[][2]={{0,1},{1,0},{0,-1},{-1,0},{1,1},{1,-1},{-1,1},{-1,-1}};


int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);cout.tie(0);
    //freopen("in.txt","r",stdin);
    //freopen("out.txt","w",stdout);
    int v1,v2,t,s,l;
    cin>>v1>>v2>>t>>s>>l;
    int sec=1,a=0,b=0,f=0;
    while(1){
        if(a-b>=t&&!f)f=s;
        if(!f)a+=v1;
        else f--;
        b+=v2;
        if(a==l||b==l)break;
        sec++;
    }
    if(a==l&&b==l)cout<<"Tie "<<sec;
    else if(a==l)cout<<"Ming "<<sec;
    else cout<<"Hong "<<sec;
    return 0;
}



B.Min Value

題意:
n使abs(ai+aj)給n個整數,找出任意兩個數使得abs(a_i+a_j)最小
使i+j在這個前提下使i+j最小
題解:
abs對於每個數相加abs最小的就是他的負數
所以直接找每個數的負數及其左右兩邊數
i+j並且提前維護序號,如果值相同儘量找到小的i+j
AC代碼

/*
    Author:zzugzx
    Lang:C++
    Blog:blog.csdn.net/qq_43756519
*/
#include<bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define pb push_back
#define mp make_pair
#define all(x) (x).begin(),(x).end()
#define endl '\n'
#define SZ(x) (int)x.size()
typedef long long ll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
const int mod=1e9+7;
//const int mod=998244353;
const double eps = 1e-10;
const double pi=acos(-1.0);
const int maxn=1e6+10;
const ll inf=0x3f3f3f3f;
const int dir[][2]={{0,1},{1,0},{0,-1},{-1,0},{1,1},{1,-1},{-1,1},{-1,-1}};

struct node{
    int x,id;
    bool operator <(const node &t)const{
        return x<t.x;
    }
}a[maxn];
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);cout.tie(0);
    //freopen("in.txt","r",stdin);
    //freopen("out.txt","w",stdout);
    int n;
    cin>>n;
    for(int i=1;i<=n;i++)cin>>a[i].x,a[i].id=i;
    sort(a+1,a+1+n);
    int ans1=inf,ans2;
    for(int i=1;i<=n;i++){
        int p=lower_bound(a+1,a+1+n,(node){-a[i].x,a[i].id})-a;
        p=max(1,p);
        if(p>1&&p-1!=i)
            if(abs(a[i].x+a[p-1].x)<ans1)ans1=abs(a[i].x+a[p-1].x),ans2=a[i].id+a[p-1].id;
            else if(abs(a[i].x+a[p-1].x)==ans1)ans2=min(ans2,a[i].id+a[p-1].id);
        if(p!=i)
            if(abs(a[i].x+a[p].x)<ans1)ans1=abs(a[i].x+a[p].x),ans2=a[i].id+a[p].id;
            else if(abs(a[i].x+a[p].x)==ans1)ans2=min(ans2,a[i].id+a[p].id);
        if(p+1<=n&&p+1!=i)
            if(abs(a[i].x+a[p+1].x)<ans1)ans1=abs(a[i].x+a[p+1].x),ans2=a[i].id+a[p+1].id;
            else if(abs(a[i].x+a[p+1].x)==ans1)ans2=min(ans2,a[i].id+a[p+1].id);
    }
    cout<<ans1<<' '<<ans2;
    return 0;
}



C. Coronavirus

題意:
nmn*m的圖中有高危路段,用*表示
每個以高危路段爲中心的九宮格都不能走
SE問從S到E最少需要多少步或者確定不能到達
題解:
先對不能走的路進行標記
枚舉整個圖如果遇到星號之間對周圍的九宮格進行標記
bfs然後直接bfs,隊列中維護座標和步數
如果座標對應的是終點輸出步數,否則最後輸出不能到達
AC代碼

/*
    Author:zzugzx
    Lang:C++
    Blog:blog.csdn.net/qq_43756519
*/
#include<bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define pb push_back
#define mp make_pair
#define all(x) (x).begin(),(x).end()
#define endl '\n'
#define SZ(x) (int)x.size()
typedef long long ll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
const int mod=1e9+7;
//const int mod=998244353;
const double eps = 1e-10;
const double pi=acos(-1.0);
const int maxn=1e6+10;
const ll inf=0x3f3f3f3f;
const int dir[][2]={{0,1},{1,0},{0,-1},{-1,0},{1,1},{1,-1},{-1,1},{-1,-1}};

char g[100][100];
bool vis[100][100];
struct node{
    int x,y,s;
};
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);cout.tie(0);
    //freopen("in.txt","r",stdin);
    //freopen("out.txt","w",stdout);
    int n,m;
    cin>>n>>m;
    int sx,sy;
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++){
            cin>>g[i][j];
            if(g[i][j]=='S')sx=i,sy=j;
        }
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
            if(g[i][j]=='*'){
                vis[i][j]=1;
                for(int k=0;k<8;k++){
                    int dx=i+dir[k][0];
                    int dy=j+dir[k][1];
                    if(dx<1||dx>n||dy<1||dy>m)continue;
                    if(g[dx][dy]=='E'){cout<<"Impossible";return 0;}
                    vis[dx][dy]=1;
                }
            }
    queue<node> q;
    q.push((node){sx,sy,0});vis[sx][sy]=1;
    while(!q.empty()){
        node p=q.front();
        q.pop();
        if(g[p.x][p.y]=='E'){cout<<p.s;return 0;}
        for(int i=0;i<4;i++){
            int dx=p.x+dir[i][0];
            int dy=p.y+dir[i][1];
            if(dx<1||dx>n||dy<1||dy>m||vis[dx][dy])continue;
            vis[dx][dy]=1;
            q.push((node){dx,dy,p.s+1});
        }
    }
    cout<<"Impossible";
    return 0;
}



D. Array

題意:
xy一個數組全部異或的值爲x,全部相加爲y
問數組最短長度是多少
題解:
codeforces round 628D原題的簡化版 codeforces~round~628 D
本場題解連接
d鏈接裏的d題有詳細題解
AC代碼

/*
    Author:zzugzx
    Lang:C++
    Blog:blog.csdn.net/qq_43756519
*/
#include<bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define pb push_back
#define mp make_pair
#define all(x) (x).begin(),(x).end()
#define endl '\n'
#define SZ(x) (int)x.size()
typedef long long ll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
const int mod=1e9+7;
//const int mod=998244353;
const double eps = 1e-10;
const double pi=acos(-1.0);
const int maxn=1e6+10;
const ll inf=0x3f3f3f3f;
const int dir[][2]={{0,1},{1,0},{0,-1},{-1,0},{1,1},{1,-1},{-1,1},{-1,-1}};


int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);cout.tie(0);
    //freopen("in.txt","r",stdin);
    //freopen("out.txt","w",stdout);
    ll u,v;
    while(cin>>u>>v){
        if(v-u<0||(v-u)%2){cout<<-1<<endl;continue;}
        ll d=v-u;
        if(!d){
            if(!u)cout<<0;
            else cout<<1;
        }
        else{
            ll t=d/2;
            if((t&u)==0)cout<<2;
            else cout<<3;
        }
        cout<<endl;
    }
    return 0;
}



G.XOR

題意:
n1n已知n,從1到n中選任意兩個數異或
這個異或的最大值爲多少
題解:
1最大值很明顯儘量是讓每個數都爲1
n101010100那麼比如n的二進制位101010100
1000000001111111那肯定是拿100000000和1111111異或
1最後全部爲1就是結果
AC代碼

/*
    Author:zzugzx
    Lang:C++
    Blog:blog.csdn.net/qq_43756519
*/
#include<bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define pb push_back
#define mp make_pair
#define all(x) (x).begin(),(x).end()
#define endl '\n'
#define SZ(x) (int)x.size()
typedef long long ll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
const int mod=1e9+7;
//const int mod=998244353;
const double eps = 1e-10;
const double pi=acos(-1.0);
const int maxn=1e6+10;
const ll inf=0x3f3f3f3f;
const int dir[][2]={{0,1},{1,0},{0,-1},{-1,0},{1,1},{1,-1},{-1,1},{-1,-1}};


int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);cout.tie(0);
    //freopen("in.txt","r",stdin);
    //freopen("out.txt","w",stdout);
    ll n;
    cin>>n;
    if(n==1){cout<<0;return 0;}
    ll ans=0,cnt=0;
    while(n)ans+=(1ll<<cnt),cnt++,n>>=1;
    cout<<ans;
    return 0;
}



H.Maze

題意:
nm+n*m的圖,圖中包含+或者-
每個點能往四個方向和自己符號不同的位置走
qq次詢問,問從某個點開始最多能走向多少個不同點
題解:
只要符號不同就可以走
並且不限制來回,可以走過去的點也可以回來
bfs所以完全可以對每個直接bfs
但是爲了防止超時,所以考慮用並查集
相鄰不同點在一個集合,只要是一個集合裏的點都可以到達
所以只要查詢每個點所在集合有多少點就是答案
AC代碼

/*
    Author:zzugzx
    Lang:C++
    Blog:blog.csdn.net/qq_43756519
*/
#include<bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define pb push_back
#define mp make_pair
#define all(x) (x).begin(),(x).end()
#define endl '\n'
#define SZ(x) (int)x.size()
typedef long long ll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
const int mod=1e9+7;
//const int mod=998244353;
const double eps = 1e-10;
const double pi=acos(-1.0);
const int maxn=1e6+10;
const ll inf=0x3f3f3f3f;
const int dir[][2]={{0,1},{1,0},{0,-1},{-1,0},{1,1},{1,-1},{-1,1},{-1,-1}};
int n,m;
char g[3010][3010];
int fa[10000010],sz[10000010];
int find(int x){
    if(fa[x]==x)return x;
    return fa[x]=find(fa[x]);
}
int id(int i,int j){
    return (i-1)*m+j;
}
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);cout.tie(0);
    //freopen("in.txt","r",stdin);
    //freopen("out.txt","w",stdout);
    int q;
    cin>>n>>m>>q;
    for(int i=1;i<=n*m;i++)fa[i]=i;
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
            cin>>g[i][j];
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
            for(int k=0;k<4;k++){
                int dx=i+dir[k][0];
                int dy=j+dir[k][1];
                if(dx<1||dx>n||dy<1||dy>m||g[dx][dy]==g[i][j])continue;
                fa[find(id(i,j))]=find(id(dx,dy));
            }

    for(int i=1;i<=n*m;i++)sz[find(i)]++;
    for(int i=1;i<=n*m;i++)sz[i]=sz[find(i)];
    while(q--){
        int x,y;
        cin>>x>>y;
        cout<<sz[id(x,y)]<<endl;
    }
    return 0;
}



I.Prime

題意:
qlrq次詢問,每次詢問l到r中有多少個素數
題解:
l,r<=1e7l,r<=1e7
所以不能每次暴力查詢
那麼就用素數篩找出所有排好序的質數
lowerboundupperbound然後用lower_bound和upper_bound進行邊界查找
看數組中間有多少個即可
AC代碼

/*
    Author:zzugzx
    Lang:C++
    Blog:blog.csdn.net/qq_43756519
*/
#include<bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define pb push_back
#define mp make_pair
#define all(x) (x).begin(),(x).end()
#define endl '\n'
#define SZ(x) (int)x.size()
typedef long long ll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
const int mod=1e9+7;
//const int mod=998244353;
const double eps = 1e-10;
const double pi=acos(-1.0);
const int maxn=1e6+10;
const ll inf=0x3f3f3f3f;
const int dir[][2]={{0,1},{1,0},{0,-1},{-1,0},{1,1},{1,-1},{-1,1},{-1,-1}};
 
int prime[maxn];
bool isprime[10000010];
int num=0;
void Prime(int n){
    memset(isprime,true,sizeof(isprime));
    for(int i=2;i<=n;i++){
        if(isprime[i]) prime[++num]=i;
        for(int j=1;j<=num;j++){
            if(i*prime[j]>n) break;
            isprime[i*prime[j]]=false;
            if(i%prime[j]==0) break;
        }
    }
}
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);cout.tie(0);
    //freopen("in.txt","r",stdin);
    //freopen("out.txt","w",stdout);
    Prime(10000000);
    int _;
    cin>>_;
    while(_--){
        int l,r;
        cin>>l>>r;
        int p=lower_bound(prime+1,prime+1+num,l)-prime-1;
        int q=upper_bound(prime+1,prime+1+num,r)-prime-1;
        cout<<q-p<<endl;
    }
    return 0;
}

J.Compare

題意:
a,ba<b<給數a,b,如果a<b輸出<
a==b=a==b輸出=
a>b>a>b輸出>
題解:
a,b<=10100000a,b<=10^{100000}
數很大,需要用高精度的判斷
python我這裏直接用了python來寫
AC代碼

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


K.Walk

題意:
t11n,m mod1e9+7t次詢問從1,1到n,m有多少種最短的走法~mod1e9+7
題解:
n,m<=1e6n,m<=1e6
dp按理說應該用dp進行轉移
最短走法應該只往下和右走
dp[i][j]=dp[i1][j]+dp[i][j1]dp[i][j]=dp[i-1][j]+dp[i][j-1]
nm但是這個n,m較大,不支持用二維數組和複雜度,並且還是多組輸入
那麼直接用組合數進行計算
(1,1)(n,m)n+m2從(1,1)到(n,m)的路徑往右和往下總共走n+m-2次
n1Cn+m2n1其中往下走包括n-1次,那麼直接C_{n+m-2}^{n-1}
n+m2n1從n+m-2步中選出n-1步往下走,剩下的步數往右走
+使所以直接預處理+逆元使用組合數
AC代碼

/*
    Author:zzugzx
    Lang:C++
    Blog:blog.csdn.net/qq_43756519
*/
#include<bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define pb push_back
#define mp make_pair
#define all(x) (x).begin(),(x).end()
#define endl '\n'
#define SZ(x) (int)x.size()
typedef long long ll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
const int mod=1e9+7;
//const int mod=998244353;
const double eps = 1e-10;
const double pi=acos(-1.0);
const int maxn=2e6+10;
const ll inf=0x3f3f3f3f;
const int dir[][2]={{0,1},{1,0},{0,-1},{-1,0},{1,1},{1,-1},{-1,1},{-1,-1}};
ll fact[maxn],inv1[maxn];
ll Pow(ll a, ll b){
	ll ans = 1;
	while(b > 0){
		if(b & 1){
			ans = ans * a % mod;
		}
		a = a * a % mod;
		b >>= 1;
	}
	return ans;
}
//逆元
ll inv(ll b){
    return Pow(b,mod-2)%mod;
}



ll C(ll n,ll m){
    if(m>n||n<0||m<0)return 0;
    if(m==0||m==n) return 1;
    ll res=(fact[n]*inv1[m]%mod*inv1[n-m])%mod;
    return res;
}

void init() {
	fact[0] = 1;
	for (int i = 1; i < maxn; i++) {
		fact[i] = fact[i - 1] * i %mod;
	}
	inv1[maxn - 1] = Pow(fact[maxn - 1], mod - 2);
	for (int i = maxn - 2; i >= 0; i--) {
		inv1[i] = inv1[i + 1] * (i + 1) %mod;
	}
}

int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);cout.tie(0);
    //freopen("in.txt","r",stdin);
    //freopen("out.txt","w",stdout);
    init();
    int _;
    cin>>_;
    while(_--){
        int n,m;
        cin>>n>>m;
        cout<<C(n+m-2,n-1)<<endl;
    }
    return 0;
}


L. Defeat the monster

題意:
n給n個人,每個人都有能力值
5要組一隊人探險,這一隊人能力極差不能超過5
問這一組最多可以有多少人
題解:
肯定需要先進行排序,然後選一段符合條件的連續子串
所以可以考慮用尺取方法去做
但是由於尺取寫起來不好下手
lowerboundupperbound所以我考慮的是lowerbound和upperbound進行查找
aijai+5j對每個數,查找他a_i-j到a_i+5-j之內的數
也就是以他爲一個點找他附近符合條件的,找儘量大的長度
AC代碼

/*
    Author:zzugzx
    Lang:C++
    Blog:blog.csdn.net/qq_43756519
*/
#include<bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define pb push_back
#define mp make_pair
#define all(x) (x).begin(),(x).end()
#define endl '\n'
#define SZ(x) (int)x.size()
typedef long long ll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
const int mod=1e9+7;
//const int mod=998244353;
const double eps = 1e-10;
const double pi=acos(-1.0);
const int maxn=1e6+10;
const ll inf=0x3f3f3f3f;
const int dir[][2]={{0,1},{1,0},{0,-1},{-1,0},{1,1},{1,-1},{-1,1},{-1,-1}};

int a[maxn];
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);cout.tie(0);
    //freopen("in.txt","r",stdin);
    //freopen("out.txt","w",stdout);
    int n;
    cin>>n;
    for(int i=1;i<=n;i++)cin>>a[i];sort(a+1,a+1+n);
    int ans=0;
    for(int i=1;i<=n;i++){
        for(int j=0;j<=5;j++){
            int p=lower_bound(a+1,a+1+n,a[i]-j)-a-1;
            int q=upper_bound(a+1,a+1+n,a[i]+5-j)-a-1;
            p=max(0,p);q=min(n,q);
            ans=max(ans,q-p);
        }
    }
    cout<<ans;
    return 0;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章