Codeforces Round #320 (Div. 2)(A~E)

Codeforces Round #320 (Div. 2)

A - Raising Bacteria

题意:

可以理解为把一个数变成二进制形式,然后统计有多少个1。

思路:

于是做法就是把一个数变成二进制形式,然后统计有多少个1。。

代码:
#include<iostream>
using namespace std;
int main(){
    int n ;
    while( cin >> n ){
        int cnt = 0 ;
        while( n ){
            if( n & 1 )
                cnt ++ ;
            n >>= 1 ;
        }
        cout << cnt << endl ;
    }
    return 0;
}

B - Finding Team Member

题意:

有2n个人,输入2n个人两两组队的(n+1)(n+2)/2种情况的得分,要求每个组成的小队分都尽可能的高,输出组队方案。

思路:

由于得分唯一,把得分映射到组队情况,然后将所有组队情况按得分排序,然后扫一遍就出结果了。

代码:
#include<iostream>
#include<algorithm>
#include<cstring>
#include<map>
#define cls( x ) memset(x,0,sizeof(x)) 
#define mp make_pair
using namespace std;

typedef long long lint;

const int maxn = 402 ;
int cnt[maxn*maxn*5] , vis[ 5 * maxn ] , te[maxn * 5];
map<int , pair<int , int> > has ;
int main(){
    //freopen("input.txt","r",stdin);
    int n ;
    while( cin >> n ){
        has.clear() ;
        int k = 0 ;
        for( int i = 2 ; i <= 2 * n ; i++ ){
            for( int j = 1 ; j <= i - 1 ; j++ ){
                cin >> cnt[k] ;
                has[cnt[k]] = mp( i , j ) ;
                k++ ;
            }
        }
        cls( vis ) ;
        sort( cnt , cnt + k ) ;
        for( int i = k - 1 ; i >= 0 ; i-- ){
            pair<int , int>p = has[cnt[i]] ;
            if( !vis[p.first] && !vis[p.second] )
                te[p.first] = p.second , te[p.second] = p.first ;
            else
                continue ;
            vis[p.first] = 1 ;
            vis[p.second] = 1 ;
        }
        for( int i = 1 ; i <= 2 * n ; i++ )
            cout << te[i] << ' ' ;
        cout << endl ;
    }
    return 0;
}

C - A Problem about Polyline

题意:

输入一个点坐标,求经过该点的一个折线函数最小x。

思路:

通过带入斜率为1这个特点,可以得到如下式子:
k=\frac{a-b}{2x},\frac{a+b}{2x}

k=ab2x,a+b2x

x=\frac{a-b}{2k},\frac{a+b}{2k}
x=ab2k,a+b2k

所以x要小则k要尽量大,又因为 x>=b x>=b 带入 x=b x=b 得到:
k=\lfloor\frac{a-b}{2b}\rfloor,\lfloor\frac{a+b}{2b}\rfloor
k=ab2b,a+b2b

再带回去:
x=min(\frac{a-b}{2*\lfloor\frac{a+b}{2b}\rfloor},\frac{a+b}{2*\lfloor\frac{a-b}{2b}\rfloor})
x=min(ab2a+b2b,a+b2ab2b)

显然,在 a>b a>b 的情况下前者较小,且由于斜率限制, a<b a<b 一定是无解的,所以答案就是 \frac{a-b}{2*\lfloor\frac{a+b}{2b}\rfloor} ab2a+b2b

代码:
#include<cstdio>
#include<iostream>
using namespace std;
typedef long long lint;

int main(){
    lint a , b ;
    while( cin >> a >> b ){
        double x = a + b ;
        double tmp = ( a - b ) / 2 / b + 1 ;
        tmp *= 2 ;
        x /= tmp ;
        if( a < b  )
            cout << -1 << endl ;
        else
            printf( "%.12f\n" , x ) ;
    }
    return 0;
}

D - “Or” Game

题意:

输入一些数字,可以将一些数字进行乘以x操作,操作共可以进行k次,求操作完后的这些数字的最大与值 。

思路:

要想与值最大,那么就必须提升最大值的二进制长度,所以所有操作应该只对一个数进行。
预处理出前缀与值和后缀与值,然后扫描一遍假设a[i]进行k次操作,维护最大值即可。

代码:
#include<cstdio>
#include<iostream>
using namespace std;
typedef long long lint;

const int maxn = 2 * 1e5 + 50 ;
lint a[maxn] , pre[maxn] , suf[maxn] ;
int main(){
    //freopen("input.txt","r",stdin);
    int n , k , x ;
    while( cin >> n >> k >> x ){
        lint mul = 1 ;
        while( k-- ) mul *= x ;
        for( int i = 0 ; i < n ; i++ )
            scanf( "%I64d" , a + i ) ;
        if( n == 1 ){
            cout << a[0] * mul << endl ;
            continue ;
        }
        pre[0] = a[0] ;
        for( int i = 1 ; i < n ; i++ )
            pre[i] = pre[i-1] | a[i] ;
        suf[n-1] = a[n-1] ;
        for( int i = n - 2 ; i >= 0 ; i-- )
            suf[i] = suf[i+1] | a[i] ;
        lint ans = ( a[0] * mul ) | suf[1] ;
        for( int i = 1 ; i < n ; i++ )
            ans = max( ans , pre[i-1] | ( a[i] * mul ) | suf[i+1] ) ;
        cout << ans << endl ;
    }
    return 0;
}

E - Weakness and Poorness

题意:

输入一些数字. s(i,j)=jk=i(akx),max1ijn|s(i,j)|

思路:

s(i,j)=,ans  k=ij(akx),=max1ijn|s(i,j)|=max1ijnmax( s(i,j) , s(i,j) )=max(max1ijns(i,j) ,max1ijns(i,j) )=max( f(x) , g(x) )

由于f(x)关于x单调递减,g(x)关于x单调递增,所以这是一个凸性函数,可以三分求得极值。

代码:
/*
* @author FreeWifi_novicer
* language : C++/C
*/
#include<cstdio>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<algorithm>
#include<string>
#include<map>
#include<set>
#include<vector>
#include<queue>

using namespace std;

#define clr( x , y ) memset(x,y,sizeof(x))
#define cls( x ) memset(x,0,sizeof(x))
#define pr( x ) cout << #x << " = " << x << endl 
#define pri( x ) cout << #x << " = " << x << " " 
#define mp make_pair
#define pb push_back
typedef long long lint;
typedef long long ll;
typedef long long LL;

const int maxn = 2e5 + 50 ;
int a[maxn] ;
int n ;
double calc( double x ){
    double ma = 0 , mi = 0 , sum = 0 , res = 0 ;
    for( int i = 0 ; i < n ; i++ ){
        sum += a[i] - x ;
        mi = min( mi , sum )  ;
        ma = max( ma , sum )  ;
        res = max( res , max( ma - sum , sum - mi ) ) ;
    }
    return res ;
}
double ts(){
    double l = -1e5 - 10 , r = 1e5 + 10 ;
    for( int i = 0 ; i < 120 ; i++ ){
        double m1 = ( l + l + r ) / 3.0 , m2 = ( l + r + r ) / 3.0 ;
        if( calc( m1 ) < calc( m2 ) )
            r = m2 ;
        else
            l = m1 ;
    }
    return calc( ( l + r ) / 2 ) ;
}
int main(){
    //freopen("input.txt","r",stdin);
    while( cin >> n ){
        for( int i = 0 ; i < n ; i++ )
            scanf( "%d" , a + i ) ;
        printf( "%.12f\n" , ts() ) ;
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值