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

Powered by:AB_IN 局外人

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

A 不一样的食物链

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

#include 
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 AC的代码,但如果有 s p j spj spj的话,这个也是能过的。
正解是用二进制, 0 0 0 1 1 1分别代表 + , − +,- +,
我用的 b f s bfs bfs

#include 
#include
#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 
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 bfs跑一遍即可,第一次到达的就是最短的,代码还可以优化,但懒得写了。。。。

#include 
#include
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
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 2,第二次 3 3 3,可以用两个的和,每一次减去一个数,从而得到下一个数。

#include
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 1的转移到女生那,然后将 2 − > n 2->n 2>n的奇数求和
  • 但男生数目是偶数,将 1 − > n 1->n 1>n的偶数求和。

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

#include
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
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));
    }
}

完结。

你可能感兴趣的:(ACM,算法)