重庆师范大学第一届ACM选拔赛

Powered by:AB_IN 局外人

不喷不喷。毕竟谁都有第一次嘛~
不过题还是挺适合我这种菜鸡的。

A 不一样的食物链

将所有生物都放进 m a p map 里,被捕食者++,再遍历 m a p map 看有没有为 0 0 的即可。

#include <bits/stdc++.h>
using namespace std;
int m;
string x,y;
map< string,int> vis;
int main()
{
    cin>>m;
    int flag=1;
    for(int i=1;i<=m;i++){
        cin>>x>>y;
        if(!vis[x]) vis[x]=0;
        vis[y]++;
    }
    for(auto i=vis.begin();i!=vis.end();i++){
        string s=i->first;
        if(!vis[s]) {flag=0;break;}
    }
    cout<<flag<<endl;
    return 0;
}

B 有趣的求和

这里放的是没有 A C AC 的代码,但如果有 s p j spj 的话,这个也是能过的。
正解是用二进制, 0 0 1 1 分别代表 + , +,-
我用的 b f s bfs

#include <bits/stdc++.h>
#include<unordered_map>
#define IOS ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
ll n,m;
struct sa{
    ll num;
    ll step;
    string s;
};
ll a[100];
queue<sa>q;
unordered_map<string,ll>vis;
int main()
{
    IOS;
    cin>>n;
    for(ll i=1;i<=n-1;i++) cin>>a[i];
    cin>>m;
    if(n==2){
        puts("0");
    }
    else{
        q.push((sa) {a[1]+a[2],2,"+"});
        q.push((sa) {a[1]-a[2],2,"-"});
        ull ans=0;
        while(!q.empty()){
            sa tmp=q.front();
            q.pop();
            if(tmp.step==n-1&&tmp.num==m){
                vis[tmp.s]++;
                ans++;
                continue;
            }
            if(tmp.step==n-1) continue;           
            q.push( (sa) {tmp.num+a[tmp.step+1],tmp.step+1,tmp.s+"+"});
            q.push( (sa) {tmp.num-a[tmp.step+1],tmp.step+1,tmp.s+"-"});
        }
        if(!ans) puts("0");
        else{
            cout<<ans<<endl;
            for(auto it=vis.begin();it!=vis.end();it++){
                cout<< it->first <<endl;
            }
        }
    }
    return 0;
}

C 统计患病人数

并查集。

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e7+10;
ll fa[N];
ll find(ll x) 
{
    if(fa[x] == x) return x;
    return fa[x] = find(fa[x]);
}
void join(ll a,ll b)
{
    int a1=find(a),b1=find(b);
    if(a1!=b1) fa[a1]=b1;
}
ll x,n,m,z,tmp,tmp1;
vector<ll>v;
int main()
{
    cin>>x>>n>>m;
    for(ll i=0;i<=x;i++) fa[i]=i;
    for(ll i=1;i<=m;i++){
        cin>>z;
        cin>>tmp1;
        for(ll i=1;i<=z-1;i++){
            cin>>tmp;
            join(tmp,tmp1);
        }
    }
    for(ll i=0;i<=x;i++){
        if(find(n)==find(i)) v.push_back(i);
    }
    cout<<v.size()<<" ";
    for(ll i=0;i<v.size();i++) cout<<v[i]<<" ";
}

D 皮皮想拜师

一样用 b f s bfs 跑一遍即可,第一次到达的就是最短的,代码还可以优化,但懒得写了。。。。

#include <bits/stdc++.h>
#include<unordered_map>
using namespace std;
int n,m;
unordered_map<int, int> a;
#define IOS ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
struct sa{
    int num;
    int step;
};
queue<sa> q;
int main()
{
    IOS;
    cin>>m>>n;
    if(n>=m){
        cout<<n-m<<endl;
    }
    else{
        q.push({n,0});
        while(!q.empty()){
            sa tmp=q.front();
            q.pop();
            if(!a[tmp.num]||a[tmp.num]>=tmp.step)
                a[tmp.num]=tmp.step;
            else continue;
            if(tmp.num==m){
                cout<<tmp.step<<endl;
                return 0;
            }
            if(tmp.num<1e5){
                q.push({tmp.num-1,tmp.step+1});
                q.push({tmp.num+1,tmp.step+1});
                q.push({tmp.num*2,tmp.step+1});
            }     
        }
    }
    return 0;
}

E 爱玩游戏的Tom

01背包板子题。
但我还是用的贪心。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
struct sa{
    ll num;
    ll imp;
    double ave;
}a[1000];
ll n,m;
bool cmp(struct sa & a,struct sa & b){
    if(a.ave!=b.ave) return a.ave>b.ave;
    else return a.imp>b.imp;
}
ll ans;
int main()
{
    cin>>n>>m;
    for(ll i=1;i<=n;i++){
        cin>>a[i].num>>a[i].imp;
        if(a[i].num==0) a[i].ave=0x3f3f3f3f;
        else a[i].ave=a[i].imp/a[i].num;
    }
    sort(a+1,a+1+n,cmp);
    for(ll i=1;i<=n;i++){
        if(a[i].num<=m){
            m-=a[i].num;
            ans+=a[i].imp;
        }
    }
    cout<<ans<<endl;
}

F 天选子

纯纯的队列模拟题。
像这种每次变化条件的,第一次 2 2 ,第二次 3 3 ,可以用两个的和,每一次减去一个数,从而得到下一个数。

#include<bits/stdc++.h>
using namespace std;
int n,m,cnt=2,sum;
int main()
{
    cin>>n>>m;
    vector<int> v;
    for(int i=1;i<=n;i++) v.push_back(i);
    while(v.size()>3){
        vector<int> tmp;
        for(int i=0;i<v.size();i++)
            if((i+1)%cnt!=0) tmp.push_back(v[i]);
        cnt=5-cnt;
        v=tmp; 
    }
    for(int i=0;i<v.size();i++) sum+=v[i];
    if(m<sum) 
        for(int i=0;i<v.size();i++){
            cout<<v[i]<<" ";
        }
    else cout<<abs(m-sum)<<endl;
}

G 团日活动

可以自己推推公式。根据贪心,肯定是最接近的两个男生一组。
分两种情况

  • 当男生数目是奇数,那么把 1 1 的转移到女生那,然后将 2 > n 2->n 的奇数求和
  • 但男生数目是偶数,将 1 > n 1->n 的偶数求和。

每种情况女生都 + 1 +1 除以 2 2 ,向下取整即可。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll t,N,n;
int main()
{
    cin>>t;
    while(t--){
        ll ans=0;
        cin>>N>>n;
        if(n%2){
            n--;
            ll n1=n/2;
            ans+=n1*(n1+2);//男
            ans+=(N-n+1)/2;//女
        }
        else{
            ll n1=n/2;
            ans+=n1*(n1+1);//男
            ans+=(N-n+1)/2;//女
        }
        cout<<ans<<endl;
    }
}

H 标准签到题

s=input()
a=s.count("ora")
if a==0:
    print("yare yare daze")
else:
    print(a)

I 炎炎消防队

浮点二分

#include<bits/stdc++.h>
using namespace std;
typedef long double ld;
#define IOS ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
ld y;
ld f(ld x){
    return 7*x*x*x*x*x*x*x+6*x*x*x*x*x*x+2*x*x*x+8*x*x-y*x;//不用pow更快
}
int t;

int main()
{
    IOS;
    cin>>t;
    while(t--){
        cin>>y;
        ld l=0,r=100;
        while(r-l>1e-5){
            ld lm=l+(r-l)/3;//这样写,防止超范围
            ld rm=r-(r-l)/3;
            if(f(lm)<f(rm)) r=rm;
            else l=lm;
        }
        printf("%.4Lf\n",f(l));
    }
}

完结。

猜你喜欢

转载自blog.csdn.net/qq_45859188/article/details/108209177