CCPC 2018吉林

Justice

题意:给了n个数ki,每个ki代表1 / pow(2,ki)是否能把这n个数分为两组,是每组的和>= 1/2;

如果给的是1,那么我需要1个1才能出来一个1/2;
给的2,需要2个
给的3,需要4个
给的4,需要8个
对于数字i,只要有pow(2,i - 1)就能出来1/2,似乎统计一下个数,判段个数是否够用就可以了,但是ki的数值1e9,pow(2,1e9)显然是不可=可能的,所以否定

既然是统计个数,那么我假设有4,是不是有以下规律:
1/ pow(2,4) + 1 /pow(2,4) = 1/pow(2,3),
1/pow(2,3) + 1 / pow(2,3) = 1 / pow(2,2)
1 / pow(2,2) + 1 / pow(2,2) = 1/ pow(2,1)
也就是说两个相同的数字 -1;
最后我只需要判断一下是否有两个1就可以了,麻烦的是需要记录一下位置
所以代码怎么写呢,应该现有一个结构体存储数字和其所在位置,放在优先队列里面(好处:可以排序,时间复杂度小)

重复找数字的操作,直到最后出现2个1;

来自队友的代码

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

struct Node{
    int val;
    vector<int> pos;
   Node(int val,int pos){
       this->val = val;
       this->pos.push_back(pos);
   };

    bool operator<(const Node &a) const{
        return val < a.val;//从大到小排序
    }
    bool operator == (const Node &a) const{
        return val == a.val;
    }

};
int t,n,num;
int main(){
   // freopen("in","r",stdin);
    ios::sync_with_stdio(0);
    cin >> t;
    for(int c = 1; c <= t; c++) {
        cout << "Case " << c << ": ";
        priority_queue<Node> que;
        cin >> n;
        for (int i = 0; i < n; i++) {
            cin >> num;
            que.push(Node(num, i));//数字存放
        }
        Node tt = que.top();
        que.pop();
        bool flag = false;
        while (!que.empty()) {
            if (tt.val == 1) {
                flag = true;
                break;
            }
            Node tt_next = que.top();
            que.pop();
            if (tt == tt_next) {
                tt.val--;
                tt.pos.insert(tt.pos.end(), tt_next.pos.begin(), tt_next.pos.end());
                que.push(tt);
                tt = que.top();
                que.pop();
            } else tt = tt_next;

        }
        if (!flag) {
            cout << "NO" << endl;
            continue;
        }
        cout << "YES" << endl;
        vector<int> ve(1e5 + 10);
        //成立的话,应该找标记的位置
        for (auto x : tt.pos) {
            ve[x] = 1;
        }
        for (int i = 0; i < n; i++)
            cout << ve[i];
        cout << endl;
        //还原
        for(int i = 0; i < n; i++)
            ve[i] = 0;
    }
    return 0;
}

The World
计算时间
陷阱:
上午12点是0点
下午12点是中午12点

#include <bits/stdc++.h>
using namespace std;
map<string,int> mp;
int t;
const string today = "Today";
const string tomorrow = "Tomorrow";
const string yesterday = "Yesterday";
int main(){
   // freopen("in","r",stdin);
    ios::sync_with_stdio(0);
    mp["London"] = 0;
    mp["Beijing"] = 8;
    mp["Washington"] = -5;
    mp["Moscow"] = 3;
    cin >> t;
    for(int  i = 1; i <= t; i++){
        cout << "Case " << i <<": ";
        int hour;string minute;string P;
        string from,to;
        string day;
        cin >> hour >> minute >> P >> from >> to;
        //cout << hour << minute << " " << P << from << " " << to << endl;
        if(P == "AM") {//上午12点是凌晨
            if(hour == 12) hour = 0;
        }else{//下午12点是中午12点
            if(hour != 12) hour += 12;
        }
        hour += mp[to] - mp[from];//计算时间

        if(hour < 0){//昨天
            hour += 24;
            day = yesterday;
            if(hour >= 12){//到了下午
                if(hour != 12)
                    hour -= 12;
                P = "PM";
            }else//上午
                P = "AM";
        }else if(hour < 24){//今天
            day = today;
            if(hour >= 12){
                if(hour != 12) hour -= 12;
                P = "PM";
            }else {
                P = "AM";
                if(!hour) hour = 12;
            }
        }else{//明天
            day = tomorrow;
            hour -= 24;
            if(hour < 12){
                if(hour == 0) hour = 12;
                P = "AM";
            }
            else {
               if(hour != 12) hour -= 12;
                P = "PM";
            }
        }
        cout << day << " " << hour << minute << " " << P << endl;

    }
    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值