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

Powered by:AB_IN 局外人

只會這些題了。。

A Race

模擬就okok

#include <bits/stdc++.h>
using namespace std;
int main() {
	int v1, v2, t, s, l;
	cin >> v1 >> v2 >> t >> s >> l;
		int s1 = 0, s2 = 0;
		int time1 = 0, time2 = 0;
		while (s1 < l && s2 < l) {
			if (s1 - s2 >= t) {
				s1 = v1 * time1;
				time2 += s;
				s2 = v2 * time2;
			}
			else {
				time1++, time2++;
				s1 = v1 * time1;
				s2 = v2 * time2;
			}
		}
		if (s1 < s2)
			cout << "Hong " << l / v2 << endl;
		else if (s1 > s2)
			cout << "Ming " << time2 << endl;
		else
			cout << "Tie " << time2 << endl;
}

C Coronavirus

bfs板子題。
手賤一個地方寫錯了,改了將近兩小時,按着標程提交了三四十次,終於找出來了。。

#include <bits/stdc++.h>
using namespace std;
int x2[] = { 0,0,1,-1 ,1,1,-1,-1 };
int y2[] = { 1,-1,0,0 ,1,-1,1,-1 };
struct sa
{
    int x;
    int y;
    int step;
};
queue<sa>q;
char a[55][55];
bool judge[55][55];
int n,m,xg,yg;
bool check(int x,int y)
{
    if (x<0||y<0||x>n||y>m) return false;
    for(int i=0;i<8;i++){
        int x5=x+x2[i];
        int y5=y+y2[i];
        if(a[x5][y5]=='*') return false;
    }
    return !judge[x][y];//最後再判斷是否經過
}
int bfs(int x,int y)
{
    q.push({x,y,0});
    judge[x][y]=true;
    while(!q.empty()){
        sa tmp=q.front();
        q.pop();
        int x3=tmp.x;
        int y3=tmp.y;
        if(a[x3][y3] == 'E') 
            return tmp.step;
        for(int i=0;i<4;i++){
            int x4=x3+x2[i];
            int y4=y3+y2[i];
            if(check(x4,y4))
            {
                q.push({x4,y4,tmp.step+1});
                judge[x4][y4]=true;//就是這!!!!!if裏都是x4,y4!!!!
            }
        }
    }
    return -1;
}
int main()
{
    ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
    while(cin>>n>>m){
    memset(judge,0,sizeof(judge));
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++){
            cin>>a[i][j];
            if(a[i][j]=='S') {xg=i;yg=j;}
        }
    }
    int ans=bfs(xg,yg);
    if(ans==-1) cout<<"Impossible"<<endl;
    else cout<<ans<<endl;
    }
    return 0;
}

G XOR

異或的最大值,那麼就得出1。怎麼出1呢?兩個數不同就出1。
比如給出10,它的二進制爲1010
那麼10以內必有一個0101。這樣兩個數異或就是1111,就是最大了。
需要特判一下1。

n=len(bin(int(input()))[2:]);ans=0
if n==1:
    print('0')
else:
    for i in range(n):
        ans+=2**i
    print(ans)
#include <bits/stdc++.h>
using namespace std;
typedef unsigned long long ll;
ll n,x=1;
int main()
{
    cin>>n;
    if(n==1)
        cout<<'0'<<endl;
    else{
        while(x<=n)  x*=2;
        cout<<x-1<<endl;
    }
    return 0;
}

I Prime

二分做法
記一下cnt是記錄當前素數個數。
這個使用的是prime數組,然後二分即可,之前提到過區間問題,全是閉的話,就左區間--,右區間不變,然後都用upper_bound即可。

#include <bits/stdc++.h>
#pragma GCC optimize(2)
#pragma GCC optimize(3)
typedef  long long ll;
const ll N=1e7+5;
ll  cnt,sum,ans,prime[N],pre[N];
bool flag[N];
using namespace std;
namespace IO{
    char ibuf[1<<21],*ip=ibuf,*ip_=ibuf;
    char obuf[1<<21],*op=obuf,*op_=obuf+(1<<21);
    inline char gc(){
        if(ip!=ip_)return *ip++;
        ip=ibuf;ip_=ip+fread(ibuf,1,1<<21,stdin);
        return ip==ip_?EOF:*ip++;
    }
    inline void pc(char c){
        if(op==op_)fwrite(obuf,1,1<<21,stdout),op=obuf;
        *op++=c;
    }
    inline ll read(){
        register ll x=0,ch=gc(),w=1;
        for(;ch<'0'||ch>'9';ch=gc())if(ch=='-')w=-1;
        for(;ch>='0'&&ch<='9';ch=gc())x=x*10+ch-48;
        return w*x;
    }
    template<class I>
    inline void write(I x){
        if(x<0)pc('-'),x=-x;
        if(x>9)write(x/10);pc(x%10+'0');
    }
    class flusher_{
    public:
        ~flusher_(){if(op!=obuf)fwrite(obuf,1,op-obuf,stdout);}
    }IO_flusher;
}
using namespace IO;
void init()
{
    memset(flag,1,sizeof(flag));
    flag[1]=cnt=0;
    for(ll i=2;i<=N;i++)
    {
        if(flag[i])
        {
            prime[++cnt]=i;
            pre[i]=cnt;
        }
        for(ll j=1;j<=cnt&&prime[j]*i<=N;j++)
        {
            flag[prime[j]*i]=0;
            if(i%prime[j]==0)break;
        }
    }
}
ll t,a,b;
int main()
{
    init();
    t=read();
    while(t--){
        a=read();b=read();
        a--;
        write(upper_bound(prime+1,prime+cnt+1,b)-upper_bound(prime+1,prime+cnt+1,a));
        pc('\n');
    }
}

前綴和做法
定義了一個數組v[N]爲前綴和數組,那加什麼呢?加的是判斷數組flag[N]
如果是True那麼加1,不是則不變。
看一看這個數組長啥樣:
在這裏插入圖片描述
每一個數都有值。
再對照着看看flag:
在這裏插入圖片描述

#include <bits/stdc++.h>
#pragma GCC optimize(2)
#pragma GCC optimize(3)
typedef  long long ll;
const ll N=1e7+5;
ll  cnt,sum,ans,prime[N],pre[N],v[N];
bool flag[N];
using namespace std;
namespace IO{
    char ibuf[1<<21],*ip=ibuf,*ip_=ibuf;
    char obuf[1<<21],*op=obuf,*op_=obuf+(1<<21);
    inline char gc(){
        if(ip!=ip_)return *ip++;
        ip=ibuf;ip_=ip+fread(ibuf,1,1<<21,stdin);
        return ip==ip_?EOF:*ip++;
    }
    inline void pc(char c){
        if(op==op_)fwrite(obuf,1,1<<21,stdout),op=obuf;
        *op++=c;
    }
    inline ll read(){
        register ll x=0,ch=gc(),w=1;
        for(;ch<'0'||ch>'9';ch=gc())if(ch=='-')w=-1;
        for(;ch>='0'&&ch<='9';ch=gc())x=x*10+ch-48;
        return w*x;
    }
    template<class I>
    inline void write(I x){
        if(x<0)pc('-'),x=-x;
        if(x>9)write(x/10);pc(x%10+'0');
    }
    class flusher_{
    public:
        ~flusher_(){if(op!=obuf)fwrite(obuf,1,op-obuf,stdout);}
    }IO_flusher;
}
using namespace IO;
void init()
{
    memset(flag,1,sizeof(flag));
    flag[1]=cnt=0;
    for(ll i=2;i<=N;i++)
    {
        if(flag[i])
        {
            prime[++cnt]=i;
            pre[i]=cnt;
        }
        for(ll j=1;j<=cnt&&prime[j]*i<=N;j++)
        {
            flag[prime[j]*i]=0;
            if(i%prime[j]==0)break;
        }
    }
}
ll t,a,b;
int main()
{
    init();
    t=read();
    for(ll i=2;i<=N;i++)//這裏變成了N
        v[i]=v[i-1]+flag[i];
    while(t--){
        a=read();b=read();
        write(v[b]-v[a-1]);
        pc('\n');
    }
}

J Compare

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

K Walk

逆元+組合數

  1. 什麼時候用逆元?
    當處理除數很大時。
  2. 逆元是什麼?
    每個數a均有唯一的與之對應的乘法逆元x,使得 ax1(modn)ax≡1(mod n)
  3. 什麼是費馬小定理?
    費馬小定理是數論中的一個重要定理。如果n是一個質數,而整數a不是n的倍數,則有 an11modna^{n-1}≡1(mod n)
  4. 怎麼用費馬小定理推導逆元公式?
    一般ACM要求的模數都是質數,所以是存在逆元的
    an11(modn) a^{n-1}≡1(mod n)
    aan21(modn) a*a^{n-2}≡1(mod n)
    abab(bbn2)(modn) \frac {a}{b}≡\frac {a}{b}*(b*b^{n-2})(mod n)((bbn2)(modn)(b*b^{n-2})(mod n)其實相當於1)
    ababn2(modn) \frac {a}{b}≡a*b^{n-2} (mod n)
    證畢。
  • 代碼注意事項
  1. 因爲 要求Cn+m2n1C_{n+m-2}^{n-1}故數組要開2*(1e6+10)
  2. 預處理將所有的階乘都取模算好。
  3. 本身求最短路徑可以用dpdp做,但是這個n,mn,m較大,不支持用二維數組和複雜度,並且還是多組輸入,所以直接用組合數算。
  4. (1,1)(1,1)(n,m)(n,m) 向下向右一共走n+m2n+m-2步,其中向下走n1n-1步,向右走m1m-1步,所以Cn+m2n1C_{n+m-2}^{n-1} 或者Cn+m2m1C_{n+m-2}^{m-1}
#include <bits/stdc++.h>
#pragma GCC optimize(2)
#pragma GCC optimize(3)
typedef unsigned long long ull;
typedef long long ll;
const ll maxn=2*(1e6+10);
const int mod = 1e9 + 7;
ll fac[maxn],t,n,m;
using namespace std;
namespace IO{
    char ibuf[1<<21],*ip=ibuf,*ip_=ibuf;
    char obuf[1<<21],*op=obuf,*op_=obuf+(1<<21);
    inline char gc(){
        if(ip!=ip_)return *ip++;
        ip=ibuf;ip_=ip+fread(ibuf,1,1<<21,stdin);
        return ip==ip_?EOF:*ip++;
    }
    inline void pc(char c){
        if(op==op_)fwrite(obuf,1,1<<21,stdout),op=obuf;
        *op++=c;
    }
    inline ll read(){
        register ll x=0,ch=gc(),w=1;
        for(;ch<'0'||ch>'9';ch=gc())if(ch=='-')w=-1;
        for(;ch>='0'&&ch<='9';ch=gc())x=x*10+ch-48;
        return w*x;
    }
    template<class I>
    inline void write(I x){
        if(x<0)pc('-'),x=-x;
        if(x>9)write(x/10);pc(x%10+'0');
    }
    class flusher_{
    public:
        ~flusher_(){if(op!=obuf)fwrite(obuf,1,op-obuf,stdout);}
    }IO_flusher;
}
using namespace IO;
ll quickmod (ll a, ll b ,ll c)
{
    ll ret=1%c;
    while(b){
        if(b&1)
            ret=ret*a%c;
        a=a*a%c;
        b=b>>1;
    }
    return ret;
}
ll inv(ll x) {
    return quickmod(x, mod-2, mod);
}
ll C(ll n,ll m){
    return fac[n]*(inv(fac[n-m])*inv(fac[m])%mod)%mod;
}
int main()
{
    fac[0]=1;
    for(int i=1;i<=maxn;i++){
        fac[i]=fac[i-1]*i%mod;
    }
    t=read();
    while(t--){
        n=read();m=read();
        write(C(n+m-2,n-1));
        pc('\n');
    }
}

L Defeat the monster

排個序,滑動窗口過一遍就行了。

#include <bits/stdc++.h>
#pragma GCC optimize(2)
#pragma GCC optimize(3)
typedef  long long ll;
const int  maxn=2e5+10;
using namespace std;
namespace IO{
    char ibuf[1<<21],*ip=ibuf,*ip_=ibuf;
    char obuf[1<<21],*op=obuf,*op_=obuf+(1<<21);
    inline char gc(){
        if(ip!=ip_)return *ip++;
        ip=ibuf;ip_=ip+fread(ibuf,1,1<<21,stdin);
        return ip==ip_?EOF:*ip++;
    }
    inline void pc(char c){
        if(op==op_)fwrite(obuf,1,1<<21,stdout),op=obuf;
        *op++=c;
    }
    inline ll read(){
        register ll x=0,ch=gc(),w=1;
        for(;ch<'0'||ch>'9';ch=gc())if(ch=='-')w=-1;
        for(;ch>='0'&&ch<='9';ch=gc())x=x*10+ch-48;
        return w*x;
    }
    template<class I>
    inline void write(I x){
        if(x<0)pc('-'),x=-x;
        if(x>9)write(x/10);pc(x%10+'0');
    }
    class flusher_{
    public:
        ~flusher_(){if(op!=obuf)fwrite(obuf,1,op-obuf,stdout);}
    }IO_flusher;
}
using namespace IO;
int a[maxn],n;
int main()
{
    n=read();
    for(int i=1;i<=n;i++)
        a[i]=read();
    sort(a+1,a+1+n);
    int i=1,j=1;
    int ans=0;
    while(i<=j&&j<=n){
        if(a[j]-a[i]>5){
            i++;
        }
       else{
            ans=max(ans,j-i+1);//基本都在指針變化前
            j++;
       }
    }
    write(ans);
    pc('\n');
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章