Codeforces Round #382 (Div. 2)

A. Ostap and Grasshopper

题意

在一维空间上,从标有’G’的位置每次向左或向右k单位问能否到达位置’T’,且中途不能停在’#’位置。

分析

暴力枚举每次能到达的位置。

#include<bits/stdc++.h>
using namespace std;
int main(){
    int n,k,g,t;
    scanf("%d %d",&n,&k);
    string s;   cin>>s;
    for(int i=0;i<n;i++)
        if(s[i] == 'G') g = i;
        else if(s[i] == 'T')    t = i;
    if(g > t)   swap(g,t);
    bool flag = 1;
    while((g+=k) < t)
        if(s[g] == '#') flag = 0;
    if(g != t)  flag = 0;
    printf("%s",flag?"YES":"NO");
}

B. Urbanization

题意

有n个人,每人有 wealthi 的财富。问如何从中选出 n1n2 个人分别组成两个集合,使得两个集合中人的平均财富和最大。

分析

ans=Σn11wealths1_in1+Σn11wealths2_in2=n2×Σn11wealths1_i+n1×Σn21wealths2_in1×n2

根据公式显然:在保证 n1<n2 的情况下,取财富最多的 n1 个人作为第一个集合,取剩余人中财富最多的 n2 个人作为第二个集合

#include<bits/stdc++.h>
using namespace std;
const int N = 1e5 + 10;
long long wlt[N];
bool cmp(int a,int b){  return a > b;   }
int main(){
    int n,n1,n2;
    scanf("%d %d %d",&n,&n1,&n2);
    if(n1 > n2) swap(n1,n2);
    for(int i=1;i<=n;i++)
        scanf("%d",&wlt[i]);
    sort(wlt+1,wlt+n+1,cmp);
    double ans = 0;
    for(int i=1;i<=(n1+n2);i++)
        wlt[i] += wlt[i-1];
    ans = wlt[n1] * 1.0 / n1 + (wlt[n1+n2] - wlt[n1]) * 1.0 / n2;
    printf("%.8lf\n",ans);
}

C. Tennis Championship

题意

n个人进行淘汰赛,在满足只有进行过比赛场数相同或差一场的两人才可安排进行比赛的条件下,进行比赛最多的人能进行几场。

分析

考虑该问题的逆命题:比赛最多的人进行k场最少需要有多少人。

显然,

  • 1场需要2人——f(1) = 2,
  • 2场需要3人——f(2) = 3,
  • 3场需要5人——f(3) = 5。
  • n场需要进行过n-1场比赛人与进行过n-2场比赛的人决胜——f(n) = f(n-1) +f(n-2);
#include<bits/stdc++.h>
using namespace std;
const long long inf = 1ll<< 62;
long long K[100] = {1,2};
void getFibo(){
    for(int i=2;;i++){
        K[i] = K[i-1] + K[i-2];
        if(K[i] > inf)  return;
    }
}
void getAns(long long n){
    int l = 1,  r = 89, mid, fin;
    while(l <= r){
        mid = (l+r) >> 1;
        if(K[mid] > n)  r = mid - 1;
        else    l = mid + 1,    fin = mid;
    }
    printf("%d\n",fin);
}
int main(){
    getFibo();
    long long n;
    scanf("%I64d",&n);
    getAns(n);
}

D. Taxes

题意

一个数n最少需要用多少个素数的和来表示。

分析

结论题。。。哥德巴赫猜想

详见 OESI A051034

#include<bits/stdc++.h>
using namespace std;
//-----------------Miller-Rabin测试------------------------//可用O(sqrt(n))的素数判断方法代替
long long pow_mod(long long a,long long i,long long mod) {
    long long ans = 1;
    while(i >= 1) {
        if(i&1) (ans *= a) %= mod;
        i >>= 1;
        (a *= a) %= mod;
    }
    return ans;
}
bool test(int n,int a,int d) {
    if(n == 2)  return true;
    if(n == a)  return true;
    if((n&1)==0)    return false;
    while(!(d&1))   d = d>>1;
    int t = pow_mod(a,d,n);
    while((d!=n-1) && (t!=1) && (t != n-1)) {
        t = (long long)t * t % n;
        d = d<<1;
    }
    return (t == n-1 || (d&1) == 1);
}
bool isPrime(int n) {   
    if(n<2) return false;
    int a[] = {2,7,61}; 
    for(int i=0;i<=2;i++)
        if(!test(n,a[i],n-1))   return false;
    return true;
}
//-----------------------------------------------------//
int main(){
    int n;
    scanf("%d",&n);
    if(isPrime(n))  printf("1");
    else if(n%2==0 || isPrime(n-2))   printf("2");
    else    printf("3");
}

E. Ostap and Tree待补

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值