2017.3.11 杭电校赛

1001 奇妙骰子
Problem Description
小黑和小白在玩卡牌游戏:每人每次选一张牌,比比谁的点数大。
但是小白有一个奇妙骰子,它能随机地让小白的点数增大0到n点(等概率)。
现在小白想知道自己的点数比小黑大的概率是多少。

Input
输入包含多组测试数据。
每组数据占一行,包含三个正整数,依次分别代表小白的点数a,小黑的点数b,奇妙骰子最大能增大的点数n。
1<=a,b,n<=1000000000

Output
每组数据请输出一个浮点数,代表小白的点数比小黑大的概率。
每组输出占一行,保留3位小数。

Sample Input
2 2 2

Sample Output
0.667
分析:算出分母分子即可

int main(){
    double a,b,x;
    while(~scanf("%lf%lf%lf",&a,&b,&x)){
        double ans=(a+x)>b? (a+x-b) :0;
        printf("%.3lf\n",ans/(1+x)<1 ? ans/(1+x) : 1);//概率不能大于1
    }
    return 0;
}

1002品位
Problem Description
小明依次拜访N个服装店,每个服装店对应一个品位值,小明每次到一个服装店都会增加该店的品位值和该店之前品位值的平均数 初始品位值为-1000,求最终的值。

Input
输入数据第一行是一个正整数T,表示测试数据有T组。

接下来的每组数据:
第一行一个整数N,表示N个服装店;
接下来N行,每行包含2个整数X, A,整数X代表第X个地铁站,整数A为该地铁站对应服装店的逼格值。
1<=N<=20000
1<=X<=N,且X保证都不相同。
0<=A<=1000

Output
对于每组数据,输出一行。
每行仅输出一个浮点数,保留2位小数,代表小明最后的品味值。

Sample Input
1
3
3 2
1 4
2 3

Sample Output
-983.50

//用树状数组过 是不是麻烦了
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream> 
int num[100002]={0},tree[100002]={0};
int n,l,r;
int lowbit(int x){
    return x&(-x);
}
int sum(int pos){
    int sum=0;
    while(pos>0){
        sum+=tree[pos];
        pos-=lowbit(pos);
    }
    return sum;
}
void plus(int pos, int num){
    while(pos<=n){
        tree[pos]+=num;
        pos+=lowbit(pos);
    }
}
int main()
{
    int kase;scanf("%d",&kase);
    while(kase--){
        memset(num,0,sizeof(num));
        memset(tree,0,sizeof(tree));
        scanf("%d",&n);
        for(int i=1;i<=n;i++){
            int p,val;
            scanf("%d%d",&p,&val);
            num[p]=val;
        }
        double summ=0;
        for(int i=1;i<=n;i++){
            plus(i,num[i]);
            if(i!=1)
                summ+=double((sum(i)-num[i]))/double(i-1);
        }
        printf("%.2lf\n",summ+sum(n)-1000);     
    }
    return 0;
}

附上树状数组模板: 参考博客
http://blog.csdn.net/u012860063/article/details/24812633

1003别睡觉啦,起来嗨
Problem Description
王尼玛是一名快乐的程序员,然而他最讨厌的事情就是起床了>_<。
所以他要定好多好多闹钟(n个,闹钟之间相互独立,时间可能相同),这些闹钟一共响足够多次时(m次)他才会起床。

现在告诉你每个闹钟第一次响的时刻,再响的间隔(t分钟),让你输出王尼玛要几点几分时才会起床 :)

(提示:再响间隔为t,意味着闹钟第i+1次响的时刻与第i次响的时刻相差t分钟)。

Input
输入包含多组测试用例。

每组数据:
第一行两个整数n,m,其中n表示王尼玛定闹钟的个数,m表示让王尼玛起床必须响过多少次闹钟。
第二行一个整数t,表示闹钟再响的间隔为t分钟。
对于接下来n行,第i行一个时间hh:mm,表示第i个闹钟第一次响的时刻。

数据保证——每个时刻都以hh:mm的形式给出(hh代表小时,mm代表分钟,0<=hh<24,0<=mm<60)。
数据保证——王尼玛不会睡到第二天:P~
数据保证——1<=n<=1000,1<=m<=500000,1<=t<=30

Output
每组数据输出一行,含有一个时间,格式为hh:mm,表示王尼玛起床的时刻(必须为合法的24小时制时刻)。

Sample Input
1 10
30
00:00
3 3
5
06:04
06:00
06:08

Sample Output
04:30
06:05

#include <queue>
#include <cstdio>
using namespace std;
struct Time{
    int h,m;
    friend bool operator<(Time t1, Time t2){
        return t1.h==t2.h?t1.m>t2.m:t1.h>t2.h;
    }
} temp,nc;//nc => next clock 
int main(){
    int n,m,t;
    char clock[8];
    while(scanf("%d%d",&n,&m)==2){
        scanf("%d", &t);
        priority_queue<Time> Q;
        for(int i=1;i<=n;i++){
            scanf(" %s", &clock);
            temp.h=clock[1]-'0'+10*(clock[0]-'0');
            temp.m=clock[4]-'0'+10*(clock[3]-'0');
            Q.push(temp);
        }
        m--;
        while(m--){
            nc=Q.top();
            Q.pop();
            nc.m+=t;
            nc.h+=nc.m/60;
            nc.m%=60;
            Q.push(nc);
        }
        nc=Q.top();
        clock[0]='0'+nc.h/10;
        clock[1]='0'+nc.h%10;
        clock[3]='0'+nc.m/10;
        clock[4]='0'+nc.m%10;
        printf("%s\n", clock);
    }
    return 0;
}
//比如top是八点钟,出队列,nc就是8:05再放进队列

1004这顿饭要怎么办
1005数论小白
Problem Description
小白最近在研究数论,已经研究了三天三夜。

这天,小黑闲着无聊,于是想考考小白,就给他出了这样一个题——
形如ax+by+cz=n (a,b,c,n都是已知正整数)的方程,是否有非负整数解(x>=0 并且 y>=0 并且 z>=0)?

小白看傻了,于是来求助你了。

Input
输入数据第一行是一个正整数T,代表输入组数。
然后是T组数据:
每组一行,输入四个正整数,依次分别代表a,b,c,n,其中:
T<=30
1<=a,b,c,n<=500000

Output
对于每组数据请输出一行。
有解输出”Yes”(不带引号),无解输出”No”(不带引号)。

Sample Input
2
1 2 3 6
3 5 6 4

Sample Output
Yes
No

暴力

#include <iostream>
#include <fstream>
#include <cstdio>
#include <sstream>
#include <set>
#include <bitset>  
#include <queue>  
#include <deque>
#include <stack> 
#include <list>
#include <vector>
#include <map>
#include <string>
#include <cstring>
#include <cmath>
#include <cctype>
#include <algorithm>

using namespace std;
typedef long long ll;
typedef set<int> Set;
typedef vector<int> Vec;
typedef set<int>::iterator sIt;
typedef vector<int>::iterator vIt;
#define mem(s,t) (memset(s,t,sizeof(s)))
#define SZ(v) (int(v.size()))
#define D(v) cout<<#v<<" "<<v<<endl
int p[500000+10];
int main(){
#ifdef LOCAL
    freopen("in.txt","r",stdin);
    freopen("o.txt","w",stdout);
#endif
    int kase;scanf("%d",&kase);
    int a,b,c,n;
    while(kase--){
        mem(p,0);
        scanf("%d%d%d%d",&a,&b,&c,&n);
        p[a]=p[b]=p[c]=1;
        for(int i=min(min(a,b),c);i<=n;i++){
            if(i>a && p[i-a]) p[i]=p[i-a];
            if(i>b && p[i-b]) p[i]=p[i-b];
            if(i>c && p[i-c]) p[i]=p[i-c];
        }
        if(p[n]) puts("Yes");
        else puts("No");
    }
    return 0;
}

1006益智游戏
Problem Description
对于任意一个ai,我们都可以使其变成a[i],a[i]^2,a[i]^4,a[i]^8,…,a[i]^(2^p)(p属于非负整数)中的任意一个。

现在想要知道:如何决定每一个数的大小,从而使得最终 “这n个数中最大的数减最小的数的差值”尽可能小呢?

Input
输入包含多组测试用例。

每组数据:
第一行是一个整数n,表示数的个数。
接下来一行是n个正整数,分别表示a[1],a[2],…a[n].

数据保证——
1<=n<=100000
1<=a[]<=10^9

Output
每组数据请输出一行,包含一个整数,表示如题所描述的尽可能小的差值。

Sample Input
2
2 4
3
3 4 5
2
2 15

Sample Output
0
2
1

维护maxn和minn即可

#include <iostream>
#include <fstream>
#include <cstdio>
#include <sstream>
#include <set>
#include <bitset>  
#include <queue>  
#include <deque>
#include <stack> 
#include <list>
#include <vector>
#include <map>
#include <string>
#include <cstring>
#include <cmath>
#include <cctype>
#include <algorithm>

using namespace std;
typedef long long ll;
typedef set<int> Set;
typedef vector<int> Vec;
typedef set<int>::iterator sIt;
typedef vector<int>::iterator vIt;
#define mem(s,t) (memset(s,t,sizeof(s)))
#define SZ(v) (int(v.size()))
#define D(v) cout<<#v<<" "<<v<<endl
ll a[100005];
int main(){
#ifdef LOCAL
    freopen("in.txt","r",stdin);
    freopen("o.txt","w",stdout);
#endif  
    int n;
    while(~scanf("%d",&n)){
        ll minn=1<<30,maxn=0;
        for(int i=0;i<n;i++){
            scanf("%lld",&a[i]);
            minn=min(minn,a[i]);
            maxn=max(maxn,a[i]);
        }
        if(minn==1){
            printf("%lld\n",maxn-1);
            continue;
        }
        for(int i=0;i<n;i++){
            while(a[i]*a[i]<maxn) a[i]*=a[i];
        }
        sort(a,a+n);
        ll ans =a[n-1]-a[0];
        for(int i=0;i<n;i++){
            a[i]*=a[i];
            maxn=max(maxn,a[i]);
            minn=min(a[i+1],a[i]);
            ans=min(ans,maxn-minn);
        }
        printf("%d\n",ans);

    }
    return 0;
}

打野顺序
Problem Description
cc和ss是好朋友。
cc很擅长玩rpg游戏,ss却怎么也玩不好,便嚷着让cc传授给他游戏技巧。于是cc给ss上了rpg游戏的第一课——打野(消灭野生生物,获得经验金钱)。
游戏中ss可以控制一个英雄,因为是教练模式,于是可以认定英雄的血量无限,英雄的攻击力为att,英雄在一次打野的时候需要同时对付n个野怪。每个野怪也有一定的血量和攻击力。
战斗采取回合制模式,每回合ss的英雄先采取行动,可以选择攻击任意一只野怪,然后所有存活状态下——即血量为正数的野怪可以攻击ss的英雄。
现在请你帮cc指点下ss,如何选择每回合的攻击对象,才可以使的ss在消灭所有野怪之后,损失的血量尽可能低呢?

Input
输入包含多组测试数据,请处理到文件结束。

对于每组数据——
第一行,包含两个整数n,ata,分别代表怪物数、英雄攻击力。
接下来n行,每行两个整数h[i],a[i],分别表示第i个怪物的血量和攻击力。

数据保证——
1<=n<=10
1<=h[], a[], att<=10000

Output
每组数据输出一行,包含一个整数,表示在消灭所有的野怪之后,损失的最小血量。

Sample Input
1 10
20 5
1 10
21 5
2 10
20 5
21 5

Sample Output
5
10
25

#include<cstdio> 
#include<algorithm>
using namespace std;
typedef long long int ll;
ll satt,vis[10010],ans,a[10010],b[10010],sum,n,m;
void dfs(int k){
    if(sum>=ans) return ;
    if(k==n){
        ans=min(ans,sum);
        return ;
    }
    for(ll i=1;i<=n;i++){
        if(!vis[i]){
            vis[i]=1;
            ll t= (a[i]-1)/m;
            sum+=t*satt;satt-=b[i];
            sum+=satt;
            dfs(k+1);
            sum-=satt;
            satt+=b[i];sum-=t*satt;
            vis[i]=0;
        }
    }
}
int main(){
    while(scanf("%lld%lld",&n,&m)==2){
        memset(vis,0,sizeof(vis));
        satt=0;
        for(int i=1;i<=n;i++){
            scanf("%d%d",&a[i],&b[i]);
            satt+=b[i];
            ans=(ll)1e15;
            sum=0;
            dfs(0);
            printf("%lld\n",ans);
        }
    }
}

1008数字迷
Problem Description
找出数字的二进制表示方法 中1的个数(即为营养价值)

一天,kirito找到了n个数,他很想知道这n个数的营养价值总和是奇数还是偶数。

Input
输入数据第一行是一个正整数T,代表输入数据的组数。
下面T组输入,每组输入如下:
第一行输入一个n,第二行输入n个数x,每两个数之间用空格隔开。
1<=T<=50
n<=30000
0<=x<=2147483647

Output
每组数据输出一行;
如果营养价值总和是奇数,请输出”odd”(输出不带引号),否则请输出”even”(输出不带引号)。

Sample Input
1
3
1 2 3

Sample Output
even

#include <cstdio>
#include <algorithm>
using namespace std;
int Count(int n){//Count 函数
    int c =0 ;
    for(c =0;n; ++c){
        n &= (n-1);// 清除最低位的1
    }
    return c ;
}
int main(){
    int kase;scanf("%d",&kase);
    while(kase--){
        int ok=0;
        int n;
        scanf("%d",&n);
        for(int i=0;i<n;i++){
            int x;
            scanf("%d",&x);
            ok+=(Count(x)&1);
        }
        if(ok&1) puts("odd");
        else puts("even");

    }
    return 0;
}

参考博客:
http://www.cnblogs.com/graphics/archive/2010/06/21/1752421.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值