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=a−b2x,a+b2x
x=\frac{a-b}{2k},\frac{a+b}{2k}
x=a−b2k,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=⌊a−b2b⌋,⌊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(a−b2∗⌊a+b2b⌋,a+b2∗⌊a−b2b⌋)
显然,在 a>b a>b 的情况下前者较小,且由于斜率限制, a<b a<b 一定是无解的,所以答案就是 \frac{a-b}{2*\lfloor\frac{a+b}{2b}\rfloor} a−b2∗⌊a+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(ak−x),求max1≤i≤j≤n|s(i,j)|
思路:
设s(i,j)=那么,ans ∑k=ij(ak−x),=max1≤i≤j≤n|s(i,j)|=max1≤i≤j≤nmax( s(i,j) , −s(i,j) )=max(max1≤i≤j≤ns(i,j) ,max1≤i≤j≤n−s(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;
}