Codeforces Round #544 (Div. 3) A B C D

7 篇文章 0 订阅
1 篇文章 0 订阅

起来才发现昨晚打的是div3 = =

Codeforces Round #544 (Div. 3)


A题

题意
给两个时间点,h1:m1,h2:m2,求他们中间的时间是什么,24小时制,保证秒数时间差为偶数,输出为xx:xx,不足的用0补齐

假思路

int main()
{  // if(fopen("in.txt","r")) freopen("in.txt","r",stdin);
    int T,n,m,k,i,sum,j,t,tmp;
    int h1,h2,m1,m2;
    scanf("%d:%d%d:%d",&h1,&m1,&h2,&m2);
    int t1 = h1*60 + m1;
    int t2 = h2*60 + m2;
    t = t2 - t1;
   // cout<<t<<endl;
    t /= 2;
    //cout<<t<<endl;
    tmp = t/60;
    int h = h1 + tmp;
    m = (t - tmp*60 + m1 )%60;
    printf("%02d:%02d\n",h,m);
    return 0;
}

t为开始时间到中间时间的秒数,然后加起来一波操作,然后wa了
睡觉的时候想起来:
m那里如果刚好是60的话,h应该++
出错的例子是:
00:01
23:59
输出了11:00
应该是:12:00

正确思路
一个是上面提到的h++,做题的时候wa了一发 蒙了,就改了个思路,计算中间时刻从00:00开始的秒数,再化成时和秒

int main()
{   if(fopen("in.txt","r")) freopen("in.txt","r",stdin);
    int T,n,m,k,i,sum,j,h,t,tmp;
    int h1,h2,m1,m2;
    scanf("%d:%d%d:%d",&h1,&m1,&h2,&m2);
    int t1 = h1*60 + m1;
    int t2 = h2*60 + m2;
    t = t2 - t1;
   // cout<<t<<endl;
    t /= 2;
   // cout<<t<<endl;
    t1 += t;
   // cout<<t1<<endl;
    h = t1/60;
    m = t1 - t1/60*60;
    printf("%02d:%02d\n",h,m);
    return 0;
}

B题

题意
给n个数字,一个k,要求两个两个数字搭配,使得这两个数字加起来是k的倍数,然后数字不可以重复用,问有多少个适合搭配的数字

思路
发现k比较小,先把n个数字mod k,变成0~k-1。他们搭配的方案最多有 k/2 + 1种。然后1和k-1搭配,2和k-2搭配。。。注意mod k = 0的数字的个数就直接加入答案,注意一下奇数个要 - 1 ,再注意一下k=6 , 3+3=6类似这种情况统计。

代码

int main()
{   if(fopen("in.txt","r")) freopen("in.txt","r",stdin);
    int T,n,m,k,i,sum,j,t,tmp;
    int cnt[105]={0},a[2*maxn];
    scanf("%d%d",&n,&k);
    for(i=0;i<n;i++){
        a[i] = read();
        cnt[a[i]%k]++;
    }
    ll ans = cnt[0]-(cnt[0]&1);
   // cout<<ans<<endl;
    for(i=1;i<=k/2;i++){
      //  cout<<i<<" "<<cnt[i]<<" "<<cnt[k-i]<<endl;
        if(k-i!=i){
            ans += min(cnt[i] , cnt[k-i])*2;
        }else ans += cnt[i]-(cnt[i]&1);
    }
    printf("%d\n",ans);
    return 0;
}

C题

题意
给出n个数字,在里面找集合,要求集合中的数字间相差不超过5,问适合条件的集合的元素最多有多少个。

假思路
= = 觉得div2 C题了,感觉是dp,写了个假的dp,结果后来发现不是。

思路
从小到大排序,然后用 upper_bound 找一找第一个比 a[ i ] + 5 大的数字在哪,然后减一下坐标,及时统计答案就行了。

int main()
{   if(fopen("in.txt","r")) freopen("in.txt","r",stdin);
    int n,a[2*maxn],ans=-1,i,k;
    scanf("%d",&n);
    for(i=0;i<n;i++) a[i] = read();
    sort(a,a+n);
    for(i=0;i<n;i++){
        k = upper_bound(a,a+n,a[i]+5)-(a+i);
      //  cout<<k<<endl;
        ans = max(ans,k);
    }
    printf("%d\n",ans);
    return 0;
}

D题

题意
给 n 组 a [ i ] 和 b [ i ],要求找到一个最合适的 d ,使得最多组 d * a [ i ] + b [ i ] = 0,输出最多有多少组。d 为实数。

思路1
比赛时候想的是统计使得 d * a [ i ] + b [ i ] = 0 成立的 d 的分子和分母,用gcd化简成最简形式,用pair<int,int>来存,用map< pair<int,int> , int >mp来存这些不同 d 的个数,然后遍历mp,来看看哪个 d 的个数最大,就是答案

不过细节有点问题,对于 a [ i ] == 0 && b [ i ] == 0 的情况,写的是mp[ make_pair(0,b[i]) ] ++,其实不对:对于全部实数d,都可以满足目标等式,不单是 d = 0 / b [ i ] 可以。醒来后补题,用flag记录这些情况,最后加在输出答案那里,就是最终答案。

= = 但这么做还是有漏洞:
就是 b [ i ] == 0 && a [ i ] != 0 的时候,mp[ make_pair(0,0) ] 应该++ ,d = 0 / 0 的情况应该统计,而这里如果直接gcd的话,统计的则是 d = 0 / ( a[i] / __gcd(0,a[i]),即 d = 0 / 1,就有问题了,所以还要特判

然后还是wa,wa在test 9 ,折腾几次发现是自己的快速读入出锅了= =、换成网上别的也不行,甚至wa在test 8。。。换成 cin 或者是 scanf 就过了。但之前一直都有用的。。应该没有写错吧。。test 9 太长了看不出哪里出问题。(知道自己快速读入出锅,有点缓不过来= =)

代码

ll read(){ // 贴一发出锅的快速读入,感觉没问题啊。。。。
    //ios_base::sync_with_stdio(false);
    //cin.tie(0);
	ll x=0;char ch=getchar(); bool flag = false;
	if(ch=='-') { flag = true; ch = getchar();}
	while(ch<'0'||ch>'9')ch=getchar();
	while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
	if(flag) return -x;  else return x;
}



int main()
{   if(fopen("in.txt","r")) freopen("in.txt","r",stdin);
    int T,n,m,k,i,sum,j,t,tmp,flag=0;
    int a[2*maxn],b[2*maxn];
    map< pi , int > mp;
    //cout<<__gcd(4,0)<<endl;
    scanf("%d",&n);
    for(i=0;i<n;i++) cin>>a[i];
    for(i=0;i<n;i++){
        cin>>b[i];
        if(a[i]==0){
            if(b[i]==0)flag++;
        }else if(b[i]==0){
            if(a[i]!=0)mp[P(0,0)]++;
        }else{
            t = b[i]/__gcd(a[i],b[i]);
            tmp = a[i]/__gcd(a[i],b[i]);
           // cout<<t<<" "<<tmp<<endl;
            mp[P(t,tmp)]++;
        }
    }
    map< pi ,int>::iterator it;
    t = 0;
    for(it = mp.begin();it!=mp.end();it++){
        t = max(it->second,t);
    }
    printf("%d\n",t+flag);
    return 0;
}

思路2
思路1没找出是快速读入出问题的时候,直接map存d的值了,思路差不多,不过也wa了= =,后来发现精度不够,要用 long double,不然:
2
999999999 1000000000
999999998 999999999
这一组输出的是2,应该输出的是1
然后快速读入这里也有问题,用回 scanf 就过了

代码

int a[2*maxn],b[2*maxn];

int main()
{   if(fopen("in.txt","r")) freopen("in.txt","r",stdin);
    int T,n,m,k,i,sum,j,t,tmp,flag=0;
    map< long double , int > mp;
    scanf("%d",&n);
    for(i=0;i<n;i++) scanf("%d",&a[i]);
    for(i=0;i<n;i++){
        scanf("%d",&b[i]);
        if(a[i]==0){
            if(b[i]==0) flag++;
        }else{
            long double tp = 1.0*b[i]/a[i];
            mp[tp]++;
        }
    }
    map< long double ,int>::iterator it;
    t = 0;
    for(it = mp.begin();it!=mp.end();it++){
        t = max(it->second,t);
    }
    printf("%d\n",t+flag);
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值