2016年山东省acm比赛题解(差l和h)

a Julyed

题意:n个单词,每天最多背m个单词,最少背多少天

分析:水题,不解释

#include<bits/stdc++.h>
using namespace std;

int main(){
    int t,n,m;
    scanf("%d",&t);
    while(t--){
        scanf("%d%d",&n,&m);
        int ans=n/m;
        if(n%m!=0)
          ans++;
        printf("%d\n",ans);
    }
    return 0;
}

b. Fibonacci

题意:把n分解为Fibonacci数列的和,并且两个数不能连续

分析:其实两个数不能连续没有用,证明一下如果n=f1+f2+x,分类讨论下,x=f2,n那么n=2*f1+f2=f2+f3=f4,如果x=f3,那么n=f1+f2+f3=f1+f4,如果x==f4  n=f1+f2+f4=f3+f4=f5,如果n>f4

n=f3+x

所以n从大到小依次减Fibonacci,然后倒序输出就ok了

#include<bits/stdc++.h>
using namespace std;
const int maxn=105;
int d[maxn],sz;

void init(){
    d[0]=d[1]=1;
    for(sz=2;;sz++){
        d[sz]=d[sz-1]+d[sz-2];
        if(d[sz]>=1e9)
          break;
    }
}

int main(){
    init();
    int t,n;
    scanf("%d",&t);
    while(t--){
        scanf("%d",&n);
        stack<int> s;
        int tmp=n;
        for(int i=sz;i>0;i--)
            if(d[i]<=n){
                s.push(d[i]);
                n-=d[i];
            }
            printf("%d=",tmp);
            int a=s.top();s.pop();
            printf("%d",a);
            while(!s.empty()){
                a=s.top();s.pop();
                printf("+%d",a);
            }
            puts("");

    }
    return 0;
}

c.Proxy

题意:0是本地计算机,n+1是服务器,1-n是代理服务器,给出每条线路的时间消耗,然后找到最短的0到n+1的路径,然后输出0处选择的第一个代理服务器,如如果不存在,输出-1,如果0-n+1直连且最短,输出0

分析:mdzz,读错题了,哎,说多了都是泪,都出的水题我们没出,dijkstra,把边倒着输入,然后找n+1-0的最短路,松弛操作记录前驱,特殊情况判断下就ok了

#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+5;
const int INF=1e9;

struct Edge{
    int from,to,dist;
    Edge(int u,int v,int w):from(u),to(v),dist(w){}
};

struct HeapNode{
    int d,u;
    bool operator < (const HeapNode& r) const{
        return d>r.d;
    }
};

struct Dijkstra{
    int n,m;
    vector<Edge> edges;
    vector<int> G[maxn];
    bool done[maxn];
    int d[maxn];
    int p[maxn];

    void init(int n){
        this->n=n;
        for(int i=0;i<n;i++)
            G[i].clear();
        edges.clear();
    }

    void AddEdges(int from,int to,int dist){
        edges.push_back(Edge(from,to,dist));
        m=edges.size();
        G[from].push_back(m-1);
    }

    void dijkstra(int s){
        priority_queue<HeapNode> q;
        for(int i=0;i<n;i++)
            d[i]=INF;
        d[s]=0;
        memset(done,0,sizeof(done));
        q.push((HeapNode){0,s});
        while(!q.empty()){
            HeapNode x=q.top();q.pop();
            int u=x.u;
            if(done[u]) continue;
            done[u]=true;
            for(int i=0;i<G[u].size();i++){
                Edge& e=edges[G[u][i]];
                if(d[e.to]>d[u]+e.dist){
                    d[e.to]=d[u]+e.dist;
                    p[e.to]=u;
                    q.push((HeapNode){d[e.to],e.to});
                }
                else if(d[e.to]==d[u]+e.dist)
                  p[e.to]=min(p[e.to],G[u][i]);
            }
        }
    }
}dijkstra;

int main(){
    int t;
    scanf("%d",&t);
    while(t--){
        int n,m;
        scanf("%d%d",&n,&m);
        dijkstra.init(n+2);
        int u,v,w;
        while(m--){
            scanf("%d%d%d",&u,&v,&w);
            dijkstra.AddEdges(v,u,w);
        }
        dijkstra.dijkstra(n+1);
        if(dijkstra.d[0]>=INF){
            puts("-1");
            continue;
        }
        if(dijkstra.p[0]==n+1){
            puts("0");
            continue;
        }
        printf("%d\n",dijkstra.p[0]);
    }
    return 0;
}

d.Swiss-system tournament

2*n个人,每个人有一个初始的分数,和能力值,按照分数排序,分数相同,序号小的在前面,然后每次(1 2)(3 4),这样的两个人比较,能力值大的+1分,小的不变,最后输出排名为k的人的编号

分析:zz题,当时没几个出的,思路题,想不出来没办法,要注意到失败的人是有序,胜利的人是有序的,+1后依然是有序的,两个数组分别存,然后按归并的思想往里插,O(n)时间完成排序,总时间复杂度O(n*logn+r*n)

#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+5;
int n,m,r;
struct node{
    int id,x,s;
    void read(int a,int b,int c){
        id=a;
        x=b;
        s=c;
    }
}v[maxn*2],v1[maxn],v2[maxn];

bool cmp(node a,node b){
    if(a.x==b.x)
      return a.id<b.id;
    return a.x>b.x;
}

void solve(){
    int l=0,r=0;
    for(int i=0;i<n;i+=2){
        int a=i,b=i+1;
        if(v[a].s<v[b].s||(v[a].s==v[b].s&&v[a].id>v[b].id))
          swap(a,b);
        v1[l++].read(v[a].id,v[a].x+1,v[a].s);
        v2[r++].read(v[b].id,v[b].x,v[b].s);
    }
    int a=0,b=0,c=0;
    while(a<l||b<r){
        if((b>=r)||(a<l&&(v1[a].x>v2[b].x||(v1[a].x==v2[b].x&&v1[a].id<v2[b].id))))
            v[c++]=v1[a++];
        else
          v[c++]=v2[b++];
        //printf("%d ",v[c-1].x);
    }
//    puts("");
}

int main(){
    int t;
    scanf("%d",&t);
    while(t--){
        scanf("%d%d%d",&n,&r,&m);
        n*=2;
        for(int i=0;i<n;i++){
            scanf("%d",&v[i].x);
            v[i].id=i;
        }
        for(int i=0;i<n;i++)
          scanf("%d",&v[i].s);
        sort(v,v+n,cmp);
        while(r--)
          solve();
        printf("%d\n",v[m-1].id+1);
    }
    return 0;
}

e.The Binding of Isaac

题意:有一些房间,周围都是空地,求只与一个房间相邻的空地数

分析:这个题都出了吧,看到第一眼以为是个搜索,没想到就一水题,n,m周围都搞成空地,然后输入就行,之间判断每个空地周围房间数

#include<bits/stdc++.h>
using namespace std;
const int maxn=105;
const int dx[]={0,0,1,-1};
const int dy[]={1,-1,0,0};
char g[maxn][maxn];
int n,m;
int judge(int x,int y){
    int count=0;
    for(int i=0;i<4;i++){
        int nx=x+dx[i];
        int ny=y+dy[i];
        if(nx<0||nx>n+1||ny<0||ny>m+1)
          continue;
        if(g[nx][ny]==‘#‘)
          count++;
    }
    return count==1?1:0;
}

int main(){
    int t;
    scanf("%d",&t);
    while(t--){
        scanf("%d%d",&n,&m);getchar();
        for(int i=0;i<=n+1;i++)g[i][0]=g[i][m+1]=‘.‘;
        for(int i=0;i<=m+1;i++)g[0][i]=g[n+1][i]=‘.‘;
        for(int i=1;i<=n;i++){
            scanf("%s",g[i]+1);
            getchar();
        }
        int ans=0;
        for(int i=0;i<=n+1;i++)
          for(int j=0;j<=m+1;j++)
            if(g[i][j]==‘#‘)
              continue;
            else
              ans+=judge(i,j);
        printf("%d\n",ans);
    }
    return 0;
}

f.Feed the monkey

题意:三个东西分别有n1,n2,n3个,每天取一个物品,但是三种物品连续取得不得超过d1,d2,d3个,问有多少取方案

分析:当时一看,算了下转态50^4*3,1e7多点,没问题,时间足够,而且非常多的状态达不到,就采用了记忆化搜索,当时脑残了,有个错就是找不到,遗憾,出来就找到了,悲哀,莫过于赛后过题

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int mod=1e9+7;
int dp[55][55][55][55][3];
int n[3],num[3];

int dfs(int a,int b,int c,int d,int e){
    int& z=dp[a][b][c][d][e];
    if(a==0&&b==0&&c==0)return z=1;
    if(z!=-1)
      return z;
    ll ans=0;
    for(int i=0;i<3;i++){
        if(i==0&&a==0)continue;
        else if(i==1&&b==0)continue;
        else if(i==2&&c==0)continue;
        int p;
        if(e==i){
            p=d+1;
            if(p>num[i])continue;
        }
        else
          p=1;
        if(i==0)
            ans+=dfs(a-1,b,c,p,i);
        else if(i==1)
          ans+=dfs(a,b-1,c,p,i);
        else if(i==2)
          ans+=dfs(a,b,c-1,p,i);
        ans%=mod;
    }
    return z=(int)ans;
}

int main(){
    int t;
    cin>>t;
    while(t--){
        for(int i=0;i<3;i++)
          cin>>n[i];
        for(int i=0;i<3;i++)
            cin>>num[i];
        ll ans=0;
        memset(dp,-1,sizeof(dp));
        for(int i=0;i<3;i++){
            if(n[i]==0)
              continue;
            if(i==0)
                ans+=dfs(n[0]-1,n[1],n[2],1,i);
            else if(i==1)
              ans+=dfs(n[0],n[1]-1,n[2],1,i);
            else if(i==2)
              ans+=dfs(n[0],n[1],n[2]-1,1,i);
            ans%=mod;
        }
        cout<<ans<<endl;

    }
    return 0;
}

g.Triple Nim

题意:nim游戏都玩过吧,把n个数字分成三堆,两人采取最佳策略,先手输

分析:先手输,也就是说三堆异或为0,然后我就往二进制上想,先想到奇数无解,因为最后的那个1,没有其他的1和他去^,然后由此我想到对应位的1只能分解为下一位的两个1,当时没想到组合数,我蒙了一个公式,决定赌一发,wa了,然后我继续考虑n中二进制有4个1的情况,然后想到一个神奇的式子(3^3-1)/2,一试,2 3个1的时候也成立,然后就搞了,a了,赛后想了下原理,比如20,二进制分解为11110,第四位必须放两个1,然后就是剩下三个1的放法了,每个1有三种方法,也就是3^3,减去第三个数什么都没得到的情况,然后(1,3,4)和(1,4,3)是同一种情况,所以/2

#include<bits/stdc++.h>
using namespace std;

int main(){
    int t,n;
    scanf("%d",&t);
    while(t--){
        scanf("%d",&n);
        if(n&1){
            puts("0");
            continue;
        }
        int count=-1;
        for(int i=1;i<=31;i++)
            if(n&(1<<i))
              count++;
        long long ans=pow(3,count)-1;
        ans/=2;
        printf("%lld\n",ans);
    }
    return 0;
}

h.Memory Leak

题意:

分析:

iRock Paper Scissors

题意:

分析:

j Execution of Paladin

题意:http://hs.178.com/201606/259352896164.html

分析:分析毛啊,没玩过炉石的伤不起啊,就这样吧,队友写的

#include<cstdio>
#include<queue>
#include<functional>
#include <iostream>
#include <vector>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
string s;
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        int n,m;
        scanf("%d%d",&n,&m);
        getchar();
        int a=0,b=0,c=0;
        for(int i=0;i<n;i++)
        {
            getline(cin,s);
            if(s[0]==‘M‘)
                a++;
            if(s[0]==‘B‘)
                b++;
            if(s[0]==‘O‘)
                c++;
        }
        int cnt=2*(b+c)+2*a*(b+c)+(n-1)*c;
        if(cnt>=m)
            printf("Mrghllghghllghg!\n");
        else
            printf("Tell you a joke, the execution of Paladin.\n");
    }
}

k.Reversed Words

题意:不用说了,一看就知道,直接上代码

#include<bits/stdc++.h>
using namespace std;
string s;
int main(){
    int t;
    scanf("%d",&t);getchar();
    while(t--){
        getline(cin,s);
        stack<string> ans;
        string tmp="";
        int len=s.length();
        for(int i=len-1;i>=0;i--)
            if(s[i]!=‘ ‘)
              tmp+=s[i];
            else{
                ans.push(tmp);
                tmp="";
            }
        cout<<tmp;
        while(!ans.empty()){
            tmp=ans.top();
            ans.pop();
            cout<<" "<<tmp;
        }
        cout<<endl;
    }
    return 0;
}

l Password

题意,6种操作,用最少的次数,把第一个数变成第二个数

分析:都是6位数,感觉记忆化搜索就可以搞,10^6*6,不大

时间: 2024-08-09 17:34:54

2016年山东省acm比赛题解(差l和h)的相关文章

“玲珑杯”ACM比赛 Round #19题解&amp;源码【A,规律,B,二分,C,牛顿迭代法,D,平衡树,E,概率dp】

A -- simple math problem Time Limit:2s Memory Limit:128MByte Submissions:1599Solved:270 SAMPLE INPUT 5 20 1314 SAMPLE OUTPUT 5 21 1317 SOLUTION “玲珑杯”ACM比赛 Round #19 题目链接:http://www.ifrog.cc/acm/problem/1145 分析: 这个题解是官方写法,官方代码如下: 1 #include <iostream>

记第五届山东省ACM程序设计比赛——遗憾并非遗憾

记第五届山东省ACM程序设计比赛 5月10日上午9点半左右,我们的队伍从学校出发,一个多小时后到达本次比赛的地点-哈尔滨工业大学. 报道,领材料,吃午饭,在哈工大的校园里逛了逛,去主楼的自习室歇息了一会.然后參加下午两点到四点的热身赛.不得不吐槽一下热身赛的题目,第一个题题目的数据范围写的是十的六次方,我们写出来提交怎么也不正确,后来快结束时看讨论板,管理人员说数据范围是十的九次方,无语了.第二个题目无输入,仅仅输出1到20之间的一个随机整数,题目上也明白说了是拼人品的题目,有的队伍"人品比較好

因为一个空格,就注定了结果——第五届山东省ACM程序设计比赛总结

应该来说这是一个很失败的结果,本届省赛铩羽而归.正如志愿者所说,打铁是一件很丢人的事情. 作为队长,完全没有想到会是这样的一次旅程.虽然因为去baidu的实习和各种offer的申请,对acm抱着能水就水绝不深究的敷衍态度.但之前着实还是参加了一些商业比赛,成绩都还可以,表面的繁盛更加放松了我的警惕.完全没有想到,正是线下赛的放松,使我线上赛的心态发生了重大的变化,并连锁反应了这一系列不理想的后果. 好多事情看起来完全是偶然因素,但是偶然中往往蕴藏着一些必然. 热身赛和去年一样,第二题是纯粹试人品

记第五届山东省ACM程序设计比赛——遗憾并不是遗憾

记第五届山东省ACM程序设计比赛 5月10日上午9点半左右,我们的队伍从学校出发,一个多小时后到达本次比赛的地点-哈尔滨工业大学. 报道,领材料,吃午饭,在哈工大的校园里逛了逛,去主楼的自习室休息了一会.然后参加下午两点到四点的热身赛.不得不吐槽一下热身赛的题目,第一个题题目的数据范围写的是十的六次方,我们写出来提交怎么也不对,后来快结束时看讨论板,管理人员说数据范围是十的九次方,无语了.第二个题目无输入,只输出1到20之间的一个随机整数,题目上也明确说了是拼人品的题目,有的队伍"人品比较好&q

2016山东省机器人比赛避障组小结

前言: 2016山东省机器人比赛差不多过去一年了,及时总结一下,给后来人一些经验,下文基本没有逻辑,全凭回忆,仅供参考,抛砖引玉. 比赛时间: 务必在7.10日之前完成报名,加入2017山东省机器人比赛官群和山科大机器人比赛官群,并及时确认报名是否完成.校赛2016年是国庆回来之后的第一个周,2016省赛好像是国庆一个月之后,可以看官方报名通知. 比赛准备: 工具:尖嘴钳.螺丝刀.万用表.剥线钳.电烙铁.焊锡等等 材料:常见的电阻电容等元器件.合适的电机.小车后轮(推荐跟买的电机配套的,务必要大

“玲珑杯”ACM比赛 Round #19 B -- Buildings (RMQ + 二分)

“玲珑杯”ACM比赛 Round #19 Start Time:2017-07-29 14:00:00 End Time:2017-07-29 16:30:00 Refresh Time:2017-07-29 16:42:55 Private B -- Buildings Time Limit:2s Memory Limit:128MByte Submissions:590Solved:151 DESCRIPTION There are nn buildings lined up, and th

Sdut 2165 Crack Mathmen(数论)(山东省ACM第二届省赛E 题)

Crack Mathmen TimeLimit: 1000ms   Memory limit: 65536K  有疑问?点这里^_^ 题目描写叙述 Since mathmen take security very seriously, theycommunicate in encrypted messages. They cipher their texts in this way: for everycharacther c in the message, they replace c wit

“玲珑杯”ACM比赛 Round #18 A 暴力水 C dp

“玲珑杯”ACM比赛 Round #18 计算几何你瞎暴力 题意:如果从一个坐标为 (x1,y1,z1)的教室走到(x2,y2,z2)的距离为 |x1−x2|+|y1−y2|+|z1−z2|.那么有多少对教室之间的距离是不超过R的呢? tags:坐标范围很小,瞎暴力 #include<iostream> #include<cstdio> #include<cstdlib> #include<algorithm> #include<cstring>

“玲珑杯”ACM比赛 Round #18

"玲珑杯"ACM比赛 Round #18 Start Time:2017-07-15 12:00:00 End Time:2017-07-15 15:46:00 A -- 计算几何你瞎暴力 Time Limit:5s Memory Limit:256MByte Submissions:1764Solved:348 DESCRIPTION 今天HHHH考完了期末考试,他在教学楼里闲逛,他看着教学楼里一间间的教室,于是开始思考: 如果从一个坐标为 (x1,y1,z1)(x1,y1,z1)的