第二届全国中医药院校程序设计竞赛

Problem A: 篮球队选拔

Time Limit: 1 Sec   Memory Limit: 128 MB
Submit: 164   Solved: 37
[ Submit][ Status][ Web Board]

Description

云南中医学院坐落于风景秀丽、四季如春的——昆明,创建于1960年,是全国第二批成立的高等中医药本科院校,为云南省唯一一所中医药本科院校。学校设有11个二级学院及2个教学部。有呈贡、白塔两个校区,占地面积871.36亩。
2016年7月2日,云南省人民政府与国家中医药管理局共建云南中医学院。
截至2016年8月,学校拥有两个校区,占地面积763.20亩,其中呈贡校本部730.33亩,白塔校区32.87亩,总建筑面积27.3万㎡。学校现有11个二级学院、2个公共课教学部、1个实验中心、1个研究院。有教职工680人,其中,专任教师591人。图书馆藏书79万册,线装古籍图书1.8万册, 电子资源总量36TB.
云南中医学院(筹)坐落于风景秀丽、四季如春的昆明,创建于1960年,是全国第二批成立的高等中医药本科院校,为云南省唯一一所中医药本科院校。学校设有11个二级学院及2个教学部。有呈贡、白塔两个校区,占地面积871.36亩,呈贡校区是全国高等中医药院校中环境最优美的校园之一,其建筑为云南省“最具艺术特色建筑”。
现在云南中医学院准备成立一支篮球队,同学们都非常热情,报名人数也非常多,为了方便选拔,体育老师们准备了一个积分制度来进行选拔,这样的做法既公平又方便。特别的选拔方式也很容易吸引同学们的兴趣。
每周体育老师们会准备许多次训练,并且通知大家时间
组队:在规定时间到达场地并且有意向参与的同学,老师随机分配组队,队伍人数老师自行分配,至少一人一队,至多五人一队
训练:两个队伍比赛结束后仍可以继续与其他结束比赛的队伍进行比赛
奖励:胜利能获得135点积分值(每次训练中首胜获得270点积分),失败则获得45点积分。自行在训练时间组织比赛或自己组队,则可获得的所有积分减少到三分之一。
技术值∈[0,2000]:技术值是对同学们篮球技术的数值化估计,会因为同学的训练而发生改变,但不会因为任何除技术外的因素影响
发挥情况∈[-1000,1000]:老师对同学篮球技术的估计是理想化的,当然在正式进行比赛时,各种影响因素也被老师数值化为一个整数(当然运气也算作操作水平的一种)
整体篮球技术:数值化后的发挥情况可以直接添加到技术值上,在同学们单独对战(斗牛)的胜利与否与双方的整体篮球技术有关,整体篮球技术高的可以获胜。(若整体篮球技术相等,则表示双方不论谁控球,都无法进球)
比赛内可以提供积分的有:篮板,抢断,盖帽,扣篮,篮板和抢断每次提供21点积分,盖帽每次提供63点积分,扣篮每次提供79点积分。
限制:每场比赛中获得积分总和不能超过300积分。
一次训练时候,a老师给出了一个新的组队方案:将所有同学分成两队,一队由他带领,一队由另外一位体育老师b老师带领。
组队的时候,a老师因为是发起者,所以他可以选择自己队的成员,也就是他选择一半的同学进入自己的队,剩下一半同学归b老师队。
然后a老师每次派出己方一人进行单挑赛,由b老师从自己队伍中选择与之比赛的队员,进球数量多的一方获胜,败者出局。当然为了防止同学过度训练,每位同学只能进行一场单挑赛。每场比赛持续五分钟,若结束时双方都未进球,则两人同时出局。
现在a老师希望自己的队伍没有人出局,请问a老师能否得到一个选人方案?

Input

 第一行包含一个正整数T(1≤T≤10)表示多组输入数据,
每组数据第一行包含一个正整数n(1≤n≤100000)表示有2n位同学参与训练
第二行包含2n个正整数表示每位同学的技术值ai(0<=ai<=2000)
第三行包含2n个正整数表示每位同学的发挥水平bi(-1000<=bi<=1000)

Output

 每组数据包含一行,若能得到a老师想要的方案,则输出"Cheat",若不能得到,则输出"Fail"。

Sample Input

2
2
1 3 2 4
1 1 1 1
1
1 2
2 1

Sample Output

Cheat
Fail

【分析】

题目都是废话...出题的时候想的就是想吓吓人,就是不想让这道题变成第一个被AC的题目,但是题意很简单,a老师希望自己的队友每场都获胜,并且a老师可以选择自己的队员,那么a老师肯定是选择水平最高的队员..那就ai+bi排个序,然后考虑能否每场都获胜,因为a老师先选择出战队员,那么b老师为了获胜一定是使用田忌赛马的比赛方式,所以显然a老师一方的最弱队员会跟b老师一方的最强队员比赛,那么能否每场都获胜就只取决于a老师方的最弱队友能否战胜b老师一方的最强队员了...
也就是说只要判断水平排序后n和n+1这两位队员的水平就可以得出结论...
【代码】
#include 
#include 
#include 
#include 
#include 
using namespace std;
int num[300000];
int main() 
{
    int pp;scanf("%d",&pp);
    while (pp--) 
    {
        int n,x;
        scanf("%d",&n);
        for (int i = 0; i < 2 * n; i++) scanf("%d",&num[i]);
        for (int i = 0; i < 2 * n; i++) {scanf("%d",&x);num[i]+=x;}
        sort(num, num + 2 * n);
        if (num[n - 1] < num[n])
            printf("Cheat\n");
        else
            printf("Fail\n");
    }
    return 0;
}


Problem B: 不存在的泳池

Time Limit: 1 Sec   Memory Limit: 128 MB
Submit: 65   Solved: 19
[ Submit][ Status][ Web Board]

Description

小w是云南中医学院的同学,有一天他看到了学校的百度百科介绍:
截止到2014年5月,云南中医学院图书馆纸本藏书74.8457万册,纸质期刊388种,馆藏线装古籍图书1.8万册,电子资源总量35TB,拥有中、外文数据库25个,电子图书29.5万册(镜像)、包库130万册。古籍线装图书1.8万余册,有39种列为本馆珍善本,如《彻滕八编》、《赵氏医贯》等明清版本、台湾文渊阁版本《四库全书》,按《全国古籍善本书总目》分类表(即:经·史·子·集四部分类)部编列、上架、供读者使用。
显然学校图书馆的占地面积非常大,于是他开始想象.....如果他有一个跟图书馆一样大的游泳池?!
如果有一个那么大的游泳池,他就可以邀请女神一起去游泳...
如果有一个那么大的游泳池,他还可以划开一半出租,收取门票费赚钱...这样等赚了一些钱之后,就招一些游泳教练来,然后对外招生,招收学生继续赚更多的钱!
如果有一个那么大的游泳池,他还能把泳池里的水全部放光...开一个吕子乔心目中最大最棒的泳池派对!
.......
等有了更多的钱,就可以在第一个泳池旁边再建一个一样大的泳池......
小w一边流口水一边想自己的未来,一想到女神看到自己事业有成,靠一个游泳池白手起家发家致富,对自己投怀送抱,高兴的根本合不拢嘴。
这时候旁边的小q作为小w的室友,随口提了一句:“这么大的泳池,你怎么换水?”
显然小w是个有原则的人,他不会让自己的泳池像不法商家一样不换水,用不干净的水给别人使用或者给自己使用。
小w百度了之后发现...淘宝里有一家店卖一种一次性抽水机,这种一次性抽水机很神奇,它有两个按钮:
1.如果泳池里的水(立方米)是3的倍数,那么可以按第一个按钮让它抽走泳池里三分之二的水
2.如果泳池里的水(立方米)是2的倍数,那么可以按第二个按钮让它抽走泳池里二分之一的水
小w虽然是个有原则的人,但是作为一个商人,他需要节省钱...而且他现在有两个泳池....但是显然这种抽水机不能把水抽光,水越少,性价比就越低。
但是两个泳池建在一起,如果两个泳池的水面不一样高,那么小w会很不开心,所以他想用这种抽水机,把两个泳池里的水抽成一样多。然后再考虑别的....当然在保证能把两个泳池里的水抽成一样多的情况下..他希望花的钱最少...
(不管了!好看最重要,好看才能吸引顾客啊!先好看!再考虑怎么换水吧)

Input

多组测试数据,给出A,B表示两个泳池当前的水量(立方米)

(1<=A,B<=10^9)

Output

每组测试数据输出一个整数表示至少需要买多少个一次性抽水机,若买多少个都不能让泳池的水相等,则输出"-1"

Sample Input

5 20
14 8
6 6

Sample Output

2
-1
0

【分析】

也是一道读完题目模拟一下就可以解决的问题,因为对总量a或者b只能进行/2或者/3的操作,想要使得a==b,那么如果存在方案,那么最终a和b会变成gcd(a,b),那么只要只要对剩下的a/gcd(a,b)和b/gcd(a,b)进行/2和/3操作判断是否能全部消掉
【代码】
#include  
int gcd(int x,int y)  
{  
    return y==0?x:gcd(y,x%y);  
}  
int main()  
{  
    int a,b;  
    while(~scanf("%d%d",&a,&b))  
    {  
        if(a==b)  
        {  
            printf("0\n");  
            continue;  
        }  
        int t=gcd(a,b);  
        a/=t;b/=t;  
        int ans=0;  
        while(a%2==0){a/=2;ans++;}  
        while(a%3==0){a/=3;ans++;}  
        while(b%2==0){b/=2;ans++;}  
        while(b%3==0){b/=3;ans++;}  
        if(a!=b)   
            printf("-1\n");  
        else     
            printf("%d\n",ans);  
    }  
    return 0;  
}  


Problem C: 调酒壶里的酸奶

Time Limit: 1 Sec   Memory Limit: 128 MB
Submit: 54   Solved: 12
[ Submit][ Status][ Web Board]

Description

最近小w学了一手调酒的技巧,这么帅的操作,说不定能靠这个俘获女神的芳心,为了在女神面前露一手,他想在学校里建一个"pub",但是显然学校不可能让他真的建一个"pub",那么他退而求次,想建一个"Yogurt shop",不能用酒,那用酸奶也行啊!
今天女神终于来光顾小w的酸奶店了!兴奋的小w拿出自己准备已久每天都仔细擦干净的装备——调酒壶、果汁机、隔冰器和计量杯、砧板、小刀....准备露一手给女神看看
但是女神却没有那么多耐心,女神只是觉得,自己买一瓶大酸奶喝不完,小瓶酸奶不够喝,所以在小w的酸奶店,说不定她可以想买多少就买多少。
于是女神告诉了小w她想要多少体积的酸奶,而小w却依旧想秀一下自己的操作,于是他决定用仅有的两个调酒壶为女神倒出女神想要的酸奶....
小w的两个调酒壶体积是不同的(一开始都是空的),小w每次可以选择一个调酒壶倒入另一个调酒壶(若A倒入B,A倒完或B倒满则停止),或者选择一个调酒壶倒光,或者选择一个调酒壶去接满酸奶.....
满心失望的小w想找一朵花,一瓣一瓣的撕下来,问问花朵女神到底喜不喜欢他...虽然这个答案是显而易见的,但是他还是想找一朵花...然而找花未果,反正花瓣不是偶数就是奇数,那他索性就用自己的操作次数作为花瓣个数吧!(找不到花我还不能脑补一朵吗...)
但是小w已经没有心情去想答案了...那么你能告诉他,需要多少步操作才能倒出女神想要的酸奶吗?

Input

输入包含多组数据,每行三个正整数a,b,c分别表示两个调酒壶的容量以及女神想要的酸奶体积,a,b的范围都在[0,100],c<=max(a,b)   

Output

一行包含一个整数表示完成要求的最少操作次数,若达不到则输出"impossible"(没有双引号)

Sample Input

10 15 11
6 5 4

Sample Output

impossible
4

【分析】

说实话就是个原题...不过这种一眼就看得出来是记忆化搜索的搜索也没什么原题这种说法了...
对每个状态都有六种情况:
1.把A倒满
2.把B倒满
3.把A倒光
4.把B倒光
5.把A倒进B
6.把B倒进A
六个情况直接搜索就可以了...当然dfs是会超时的,需要用记忆化搜索
【代码】
#include   
#include   
#include   
#include   
#include   
using namespace std;  
int A,B,C;  
int vis[200][200],dis[200][200];  
struct xx{  
    int a,b;  
    xx(int a,int b):a(a),b(b){}  
};  
 
int bfs()  
{  
    queue q;
    memset(vis,0,sizeof(vis));  
    memset(dis,0,sizeof(dis));
    dis[0][0]=0;  
    vis[0][0]=1;  
    q.push(xx(0,0));  
    while(!q.empty())  
    {  
        xx x=q.front();
        q.pop();  
        for(int i=1;i<=6;i++)  
        {  
            int X,Y;  
            if(i==1){X=A;Y=x.b;}  
            if(i==2){X=x.a; Y=B;}  
            if(i==3){X=0; Y=x.b;}  
            if(i==4){X=x.a; Y=0;}  
            if(i==5){X=x.a+x.b>=B?x.a+x.b-B:0;Y=x.a+x.b>=B?B:x.a+x.b;}  
            if(i==6){X=x.a+x.b>=A?A:x.a+x.b;Y=x.a+x.b>=A?x.a+x.b-A:0;}  
            if(!vis[X][Y])  
            {  
                vis[X][Y]=1;  
                dis[X][Y]=dis[x.a][x.b]+1;  
                if(X==C||Y==C) return dis[X][Y];
                q.push(xx(X,Y));  
            }  
        }  
    }  
    return -1;  
}  
int main()  
{  
    while (~scanf("%d%d%d",&A,&B,&C))
    {
        int ans=bfs();
        if (ans!=-1) printf("%d\n",ans);
        else printf("impossible\n");
    }
    return 0;  
}  


Problem D: 过分的谜题

Time Limit: 1 Sec   Memory Limit: 128 MB
Submit: 58   Solved: 30
[ Submit][ Status][ Web Board]

Description

2060年是云南中医学院的百年校庆,于是学生会的同学们搞了一个连续猜谜活动:共有10个谜题,现在告诉所有人第一个谜题,每个谜题的答案就是下一个谜题的线索....成功破解最后一个谜题后,答案就是指向奖励的线索
在所有同学们的努力下,全校同学们获得了最后一个谜题,这个谜题有几十张纸,上面全是密密麻麻的数字以及'.'
第一页内容如下:
1,2,3,4,5,6
4,1,5,2,6,3
2,4,6,1,3,5
1,2,3,4,5,6
———3

1,2,3,4....32
.............
.............
———10

有细心的同学发现,这是对一组1-2n的序列进行如下移动:每次将前n个数字取出,按顺序依次插入到位于n+1,n+2...2n的数字后面,最后的数字表示多少次移动后会变回原来的序列
第二页内容如下:
1,2,3,4....64
.............
.............
———?

1,2,3,4....140
.............
.............
———?

同学们发现,越往后翻,这个序列的长度就越长,前面十几二十个数字的序列同学们还可以一步一步模拟做出来,但是到后来几千甚至上万的长度,就没有办法计算了,甚至中间一步做错,就步步都错。
这个谜题真是太过分了!但是奖励就在眼前,只要计算出所有答案,所有答案就是指引同学们获得奖励的线索,那么现在问题来了,同学们除了发现上面的n=最后那个数字/2之外,没有办法给你任何帮助,而作为一个计算机科学与技术专业的大佬,你自然就成为了同学们心目中拯救他们的英雄,所以你能不能写一个程序,当你知道n是多少的时候,可以直接得出答案呢?

Input

多组测试数据.每组数据的第一行包含一个正整数n(1<= n<=10000).

Output

每组数据输出一行整数表示最少需要经过几次移动能变回原序列,若不能,则输出"-1"

Sample Input

3
16

Sample Output

3
10

【分析】

稍微模拟一下就会发现,每个数的位置变化就是当前位置编号*2%(n+1)
那么题目里只问多少次会变回原来的序列,那显然只要挑一个数盯着看它什么时候回去,那其他的数字必然也已经回去
对于-1这个情况...因为题目给定的保证是2n,为偶数,那就不可能会有-1的情况了
【代码】
#include   
#include   
using namespace std;  
int main()  
{  
    int n;  
    while (~scanf("%d",&n))  
    {  
        int ans=1;  
        n*=2;  
        int x=2;  
        while (x!=1)  
        {  
            ans++;  
            x=(x*2)%(n+1);  
        }  
        printf("%d\n",ans);  
    }  
    return 0;
}     

Problem E: 小C的数学问题

Time Limit: 1 Sec   Memory Limit: 128 MB
Submit: 50   Solved: 13
[ Submit][ Status][ Web Board]

Description

小C是个云南中医学院的大一新生,在某个星期二,他的高数老师扔给了他一个问题。
让他在1天的时间内给出答案。
但是小C不会这问题,现在他来请教你。
请你帮他解决这个问题。
有n个数,每个数有权值。
数学老师定义了区间价值为区间和乘上区间内的最小值。
现在要你找出有最大区间价值的区间是什么,并输出区间价值。

Input

每个输入文件只包含单组数据。
第一行一个整数n。(1 <= n <= 100000)
第二行n个整数a_1,a_2,...,a_n。(0 <= a_i <= 1000000)

Output

第一行输出一个整数,表示最大的区间价值。
第二行输出两个整数,表示区间的起点和终点。
保证答案唯一。

Sample Input

6
10 1 9 4 5 9

Sample Output

108
3 6

【分析】

原意呢是个单调栈的应用,应该是本场比赛最难题了。
但是其实只要知道一点,对于每个ai,它所影响的区间其实就是向前遍历到比它小的数后一位,向后遍历到比它小的数前一位,那么这个区间就是这个ai所影响的区间,这样考虑的话复杂度就会比O(n^2)快,然后在这个思路的基础上,用set啊链表啊维护一下当前位置往前到哪里往后到哪里,只要能把求区间的步骤优化掉,随便怎么做可以
【代码】
set维护
#include
using namespace std;
typedef long long ll;
const ll maxn=100010;
 
struct node
{
    ll x,id;
    friend bool operator<(const node&a,const node&b)
    {
        return a.xs1,s2;
ll add[maxn];
 
int main()
{
    ll n;
    while(scanf("%lld",&n)==1)
    {
        add[0]=0; 
        s1.clear();
        s2.clear();
        set::iterator it;
        for(ll i=1;i<=n;i++)
        {
            a[i].id=i;
            scanf("%lld",&a[i].x);
            add[i]=add[i-1]+a[i].x;
        }
        ll ans=-1,l,r;
        s1.insert(n+1);
        s2.insert(n+1);
        sort(a+1,a+n+1);
        for(ll i=1;i<=n;i++)
        {
            ll L=i,R=i;
            while(a[R+1].x==a[L].x&&R<=n) R++;   
            for(ll j=L;j<=R;j++)
            {
                it=s2.lower_bound(n+1-a[j].id);
                ll tl=n+1-*it;
                it=s1.lower_bound(a[j].id);
                ll tr=*it;
                ll tmp=(add[tr-1]-add[tl])*a[j].x;
                if(tmp>ans)
                {
                    ans=tmp;
                    l=tl+1,r=tr-1;
                }
            }
            for(ll j=L;j<=R;j++)
            {
                s1.insert(a[j].id);
                s2.insert(n+1-a[j].id);
            }
            i=R;
        }
        printf("%lld\n%lld %lld\n",ans,l,r);
    }
    return 0;
}

单调栈
#include 
#include 
#include 
#include 
#include 
#include 
#include 
using namespace std;
#define ALL(v) (v).begin(),(v).end()
#define cl(a,b) memset(a,b,sizeof(a))
#define clr clear()
typedef long long LL;
const int maxn = 100000 + 10;
LL sum[maxn];
struct Node{
  int v,l,r;
}a[maxn],b[maxn];
int main()
{
#ifdef local
  freopen("test8.in","r",stdin);
  freopen("test8.out","w",stdout);
  clock_t start_time=clock();
#endif
  int n;
  while(~scanf("%d",&n)) {
    assert(1 <= n <= 100000);
    for (int i = 1; i <= n; i++) {
      scanf("%d",&a[i].v);a[i].l = a[i].r = i;
      assert(0 <= a[i].v && a[i].v <= 1000000);
      sum[i] = sum[i-1] + a[i].v;
    }
    stackq;
    Node t;
    int ind = 0,L,R;
    for (int i = 1; i <= n; i++) {
      if(q.empty()) {
        q.push(a[i]);
      }
      else {
        while (!q.empty() && q.top().v >= a[i].v) {
          t = q.top();q.pop();
          a[i].l = t.l;
          b[ind++] = t;
          if(!q.empty())q.top().r = t.r; 
        }
        q.push(a[i]);
      }
    }
    Node tmp = q.top();q.pop();
    b[ind++] = tmp;
    while(!q.empty()) {
      t = q.top();q.pop();
      t.r = tmp.r;
      b[ind++] = t;
    }
    LL ans = -1;
    for (int i = 0; i < ind; i++) {
      LL s = b[i].v * (sum[b[i].r] - sum[b[i].l-1]);
      if(ans < s) {
        ans = s;
        L = b[i].l;
        R = b[i].r;
      }
    }
    printf("%lld\n%d %d\n",ans,L,R);
  }
#ifdef local
  clock_t end_time=clock();
  double run_time = (double)(end_time - start_time) / CLOCKS_PER_SEC * 1000;
  cerr<


Problem F: fps游戏

Time Limit: 1 Sec   Memory Limit: 128 MB
Submit: 150   Solved: 27
[ Submit][ Status][ Web Board]

Description

fps游戏是第一人称射击游戏。这类游戏有一个很重要的技巧也是基本功之一的,是压枪。
为了模拟真实环境,在游戏里你每开一枪,枪口都会往上和左右浮动。
如果你想使枪口在某个范围内,为了提高精准度,你就必须压枪。
而且每把枪的后坐力不同和有效打击距离不同,就需要对每把枪都很熟悉,能很快的计算出在多远距离外开枪枪口会往上和左右浮动多少。
现在只考虑枪的垂直浮动。
假设在d米外有一个靶子,初始枪口正对靶心的圆心,靶心是个半径为r米的圆,现在你要射击c次。(你可以把枪看成一个点)。
为了省力,要使压枪次数最少。
只有当在靶上的射击位置在靶心之外时才需要压枪。
每次压枪,枪口都会回到上次的射击位置。
每次开枪最多只能压一次枪,不能连续压枪。

Input

 每个输入文件只包含一组数据。
包含3个正整数d,r,c和1个实数a(d,r,c意义如上文所述,a是每次开枪,枪口向上浮动的角度)。
(1 <= d,r <= 100,0 <= c <= 1000000,0 <= a < 90)

Output

 一个整数,表示压枪的最少次数。

Sample Input

10 1 10 3

Sample Output

8

【分析】

考验高中数学水平的时候到了....只要算算到哪一枪开始会脱靶,那么后面的统统都需要压枪...直接计算就可以
【代码】
#include
using namespace std;
const double pi=acos(-1);
  
int main()
{   
    double a;
    int d,r,c;
      
    scanf("%d%d%d%lf",&d,&r,&c,&a);
      
    double sig=atan(1.0*r/d);
    sig=sig/pi*180;
      
    int t=sig/a+1;
          
    printf("%d\n",max(0,c-t));
    return 0;   
} 


Problem G: 闪闪发光

Time Limit: 1 Sec   Memory Limit: 128 MB
Submit: 49   Solved: 16
[ Submit][ Status][ Web Board]

Description


一所位于云南昆明的中医药本科院校--云南中医学院。

因为报考某专业的人数骤减,正面临着停招的危机。

其中有九名少女想到一条妙计——成为偶像,

只要她们成为偶像,学校的名气便会增加,而报考的人数亦会上升。

就这样,九位个性鲜明的少女决定一起努力成为偶像。

希望可以凭借偶像的名气增加生源来挽救自己所喜爱的专业,让自己的学校闪闪发光。

她们为了成为偶像,第一步对于她们来说是减肥!

这里有n个重物,第i个重物的重量是2^{w_i}。她们每天任务要完成的重量是n个重物的重量和。

每次举重的重量和必须是2的幂,重物数量不要求。

但是为了方便,要使举重的次数最少。

Input

多组数据。
每组数据第一行一个整数n。(1 <= n <= 10^6)
第二行有n个整数w_1,w_2,...,w_n。(0 <= w_i <= 1000000)

Output

输出最少的举重次数。

Sample Input

5
1 1 2 3 3

Sample Output

2

HINT

1,1,2一组;

3,3一组。

【分析】
数据不大,就100w,直接桶排序...就可以了
当然不会卡排序,sort之后从小的开始往上匹配,凑对进位继续凑....一样可以用set维护
反正没有卡时限,只要想的到,怎么做都可以

【代码】
#include
using namespace std;
 
sets;
 
int main()
{
    int n;
    while(scanf("%d",&n)==1)
    {
        s.clear();
        for(int i=1;i<=n;i++)
        {
            int x;
            scanf("%d",&x); 
            if(s.find(x)!=s.end())
            {
                do
                {
                    s.erase(x);
                    x=x+1;  
                }   
                while(s.find(x)!=s.end());      
            }
            s.insert(x);                        
        }
        printf("%d\n",s.size());    
    }
    return 0;
}


Problem H: 流连人间的苏苏

Time Limit: 1 Sec   Memory Limit: 128 MB
Submit: 93   Solved: 30
[ Submit][ Status][ Web Board]

Description

苏苏在做红尘仙的任务时,发现坐落于风景秀丽、四季如春的昆明市的云南中医学院。

没过多久,苏苏就喜欢上了这个学校。以致于苏苏忘了回涂山的时间,现在她只剩下d天的时间待在云南中医学院。由于时间紧迫,苏苏想方设法为建设更好的云南中医学院。

假设学校里某条街道有n个房子。

每天选择两个门牌号l、r,给这两个门牌号之间的所有房子的门前都栽一棵树,已经有树的不需要再种。

苏苏想知道在某天,有哪些房子前有树。

Input

每个输入文件只有一组数据
第一行包含n,d。(1 <= n,d <= 1000)
接下来d行,每行包含两个整数l,r(1 <= l <= r <= n)

Output

输出d行。
每行输出门牌号的区间。每个区间以逗号分隔。
具体看样例。

Sample Input

10 4
1 3
2 4
5 6
8 10

Sample Output

[1,3]
[1,4]
[1,6]
[1,6],[8,10]

【分析】

按题意直接做就行,无论优不优化..反正数据非常小
【代码】
#include
using namespace std;
  
int main()
{   
    int n,d,v[1010];
    scanf("%d%d",&n,&d);
    memset(v,0,sizeof(v));
    while(d--)
    {
        int l,r,t=0;
        scanf("%d%d",&l,&r);
        for(int i=l;i<=r;i++) v[i]=1;
         
        for(int i=1;i<=n;i++)
        {
            if(v[i]) 
            {
                if(t) printf(","); t=1;
                printf("[%d,",i);
                while(v[i]&&i<=n) i++;
                printf("%d]",i-1);
            }
        }
        printf("\n");
    }
    return 0;   
} 

Problem I: 奔赴云南

Time Limit: 1 Sec   Memory Limit: 128 MB
Submit: 121   Solved: 36
[ Submit][ Status][ Web Board]

Description

第二届全国中医药程序设计大赛在云南中医学院举行,全国各中医药院校从全国各地奔赴云南。
每个人的车票或机票上都会有如下信息:

地名 出发时间 到达时间 
  • 地名:长度不超过20
  • 出发时间: 格式hhmm
  • 到达时间: 格式hhmm

(0 <= hh <= 23,0 <= mm <= 59)
但是他们想知道在路上所花费的时间总共是多少。
现在请你编写程序帮助他们计算时间。

Input

多组数据
每组数据有一个字符串s和两个整数Time1,Time2,分别表示地名,出发时间,到达时间。 

保证 到达时间 >= 出发时间

Output

输出旅途时间。格式见样例。

Sample Input

Hangzhou 1245 1723

Sample Output

Hangzhou to Kunming: 04:38

【分析】

签到题之一,把四位数时间换算成分钟,做完减法再换算回时间即可
【代码】
#include 
int main()
{
    char s[1000];
    int time1,time2;
    while (~scanf("%s%d%d",s,&time1,&time2))
    {
        int ans = time2 / 100 * 60 + time2 % 100 - time1 / 100 * 60 - time1 % 100;
        printf("%s to Kunming: %02d:%02d\n",s,ans/60,ans%60);   
    }
    return 0;
}


Problem J: TCMPC进阶之路

Time Limit: 1 Sec   Memory Limit: 128 MB
Submit: 47   Solved: 42
[ Submit][ Status][ Web Board]

Description

小w是云南中医学院计算机专业的一名学生,最近决心开始好好学习(当然是因为太菜被女神嫌弃了..)
作为一个超级菜的菜鸟,进步的最好方式就是奋发图强努力刷题!于是小w开始在ZCMUOJ中做题。ZCMUOJ新开了一个叫的专题,引进了一个新模式——积分系统,积分越多,账号称号就越高级:
[0-50]:菜鸟
(50-500]:入门
(500-2000]:黑铁级入门选手
(2000-8000]:青铜级入门选手
(8000-20000]:白银级入门选手
(20000-80000]:黄金级入门选手
(80000-200000]:钻石级入门选手
(200000-500000]:专业级入门选手
(500000-1000000]:TCMPC热身赛选手
(1000000-2000000]:TCMPC正赛选手
(2000000-5000000]:TCMPC铜牌选手
.........
当然,每道题目都有它相应的积分,ID为1的题目AC后会获得1分,ID为2的题目AC后获得2分...ID为i的题目AC后会获得i分,那么现在小w为了成为女神心目中的大神,决定从第一题开始做,绝不跳过任何题目,严格按顺序往下做。
那么现在小w已经做到第n题了,但是积分系统却没有显示个人积分,所以他想知道他现在的积分是多少,以便计算还需要多少题才能进阶,以此给自己动力,你能帮他吗?

Input

多组数据,第一行输入一个整数T(1≤T≤10000)表示数据组数
以下T行,每行输入一个正整数n(1≤n≤10000)表示小w当前做到第n题(第n题也已AC),且题目编号是有序的。

Output

每行输出一个整数表示小w当前的积分

Sample Input

2
5
10

Sample Output

15
55

【分析】

签到题之二,1到n求和...全场AC题
【代码】
#include 
typedef long long LL;
 
int main()
{
  int T;scanf("%d",&T);
  while(T--) {
    LL n;scanf("%lld",&n);
    LL ans = (1 + n) * n / 2;
    printf("%lld\n",ans);
  }
  return 0;
}




你可能感兴趣的:(zcmu,acm,网络赛)