Codeforces Round #652 (Div. 2)A、B、C、D

题目
A题意:给出一个n条边的正多边形可以任意旋转,问能否使至少一边平行x轴,一条边平行y轴。
解法:该图形得关于x轴和y轴对称能像正方形一样被4等分,所以是4得倍数。

void solve(){
    int n ;
    cin >> n ;
    if(n%4==0){
        cout << "YES" << endl;
    }else{
        cout << "NO" << endl;
    }
}

B题意:给出一个01字符串,操作:如果存在两个字符\(s_i = 1 , s_{i+1} = 0\)可以选择任意一个删除。经过操作后,输出字典序最小得字符串。
解法:找到第一个1,最后一个0,这之间得字符串除最后一个零都可以删除,如果没找到则原串输出。

const int maxn = 1e5+9;
char s[maxn];
void solve(){
    int n ;
    cin >> n ;
    scanf("%s" , s+1);
    int index = -1;
    red(i , n , 1){
        if(s[i] == '0'){
            index = i ;
            break;
        }
    }
    int index2 = -1 ;
    rep(i , 1 , index-1){
        if(s[i] == '1'){
            index2 = i ;
            break;
        }
    }
    if(index != -1 && index2 != -1){
        rep(i , 1 , n){
            if(i >= index2 && i < index){
                continue;
            }else{
                cout << s[i] ;
            }
        }
        cout << endl;
    }else{
        printf("%s" , s+1);
        cout << endl;
    }
}

C题意:给出n个数ai,k个人每个分配wi给数,定义每个人得和为该人获得得最大值加最小值之和,问所以人之和最大为多少。
解法:排序,贪心。

const int maxn = 2e5+9;
vector<int>v[maxn];
void solve(){
    int n , k ;
    cin >> n >> k ;
    rep(i , 0 , n) v[i].clear();
    vector<int>a(n) , w(k);
    rep(i , 0 , n-1){
        cin >> a[i];
    }
    rep(i , 0 , k-1){
        cin >> w[i];
    }
    sort(all(a));
    sort(all(w));
    reverse(all(a));
    rep(i , 0 , k-1){//按w从小到大分配,依次从大到小分配a给每个人
        v[i].pb(a[i]);
        w[i]--;
    }
    int j = k ;//前k个数已经分配完毕,从第k大一直到最小值
    rep(i , 0 , k-1){同样按w从小到大分配
        while(w[i]){
            v[i].pb(a[j]);
            j++;
            w[i]--;
        }
    }
    int ans = 0 ;
    rep(i , 0 , k-1){
        ans += v[i][0] + v[i][size(v[i])-1] ;//最大加最小
    }
    cout << ans << endl;
}

D题意:最初有一个结点,衍生规则如下:

  • 如果结点 u 没有子结点,添加 1 个子结点
  • 如果结点 u 有 1 个子结点,添加 2 个子结点
  • 如果结点 u 有 3 个子结点,跳过该结点


爪形结构如下:

问可以在 \(level_n\) 选出几个互不相交的爪形结构。
解法:根据前前四个level,可以发现有\(level_i由两个level_{i-2}、一个level_{i-1}和一个根节点构成\)
所以有递推式:\(dp[i] = 2*dp[i-2] + dp[i-1] + (i\%3==0)\),当i是3得倍数时,根节点可以作为1个爪形且不影响其子树得爪形。

const int maxn = 2e6+9;
int n , k ;
int dp[maxn];
void init(){
    dp[1] = dp[2] = 0 ;
    dp[3] = dp[4] = 1 ;
    rep(i , 5 , 2e6){
        dp[i] = (2*dp[i-2] + dp[i-1] + (i%3==0))%mod;
    }
}
void solve(){
    int n ;
    cin >> n ;
    cout << 4*dp[n]%mod << endl;
}
posted @ 2020-06-25 17:48  无名菜鸟1  阅读(135)  评论(0编辑  收藏  举报