Educational Codeforces Round 170 (Rated for Div. 2)(A-D)

想补个E来着,不是很会

A-Two Screens

 思路

由题意就可以知道快捷的方式是只能在复制过程中将其中一个字符串完全放到另一个字符串上面,实际上就是最大公共前缀

代码

void solve() {
    string s1, s2;
    cin >> s1 >> s2;
    ll len;
    len = min(s1.length(), s2.length());
    ll ans = 0;
    for (int i = 0; i < len; i++) {
        if (s1[i] == s2[i]) {
            ans++;
        }
        else {
            break;
        }
    }
    if (ans == 0) {
        cout << s1.length() + s2.length();
        return;
    }
    cout << s1.length() + s2.length() - ans + 1;
}

 B-Binomial Coefficients, Kind Of

思路 

按照题意模拟之后会发现形成这样的序列

1

1 1

1 2 1

1 2 4 1

1 2 4 8 1

实际上就是2的ki次方,这边需要采取快速幂 

代码

ll ksm(ll x, ll y) {
    ll ans = 1;
    while (y) {
        if (y & 1) {
            ans = ans % mod * x % mod;
        }
        ans = ans % mod;
        x = x % mod * x % mod;
        x = x % mod;
        y >>= 1;
    }
    return ans;
}
ll getx(ll x) {
    return ksm(x, mod - 2) % mod;
}
void solve() {
    ll n;
    cin >> n;
    
    vectorarr(n + 2);
    vectorbrr(n + 2);
    for (int i = 1; i <= n; i++) {
        cin >> arr[i];
    }
    for (int i = 1; i <= n; i++) {
        cin >> brr[i];
        
    }
    for (int i = 1; i <= n; i++) {
        cout << ksm(2, brr[i])  << endl;
    }
}

 C-New Game

思路

想麻烦了其实,

首先用个map存入所有数出现的数量(map会自行排序,所以遍历就是重大到小),然后进行离散化,这边有个特点如果当前位置的数等于前面的数加1,就放到后面,不是就放到后面的后面,然后遍历,遇到0就重置,其他就加,如过大于k,就把前面的删了

代码 

void solve() {
    ll n, k;
    cin >> n >> k;
    maparr;
    for (int i = 1; i <= n; i++) {
        ll a;
        cin >> a;
        arr[a]++;
    }
    mapbrr;
    ll top = 0;
    for (auto now : arr) {
        brr[++top] = now.first;
    }
    vectorcrr(3 * n + 2);
    ll top2 = 1;
    crr[top2] = arr[brr[1]];
    for (int i = 2; i <= top; i++) {
        if (brr[i] == brr[i - 1] + 1) {
            crr[++top2] = arr[brr[i]];
        }
        else {
            ++top2;
            crr[++top2] = arr[brr[i]];
        }
    }
    ll ans = 0;
    ll sum = 0;
    ll sum2 = 0;
    for (int i = 1; i <= top2; i++) {
        if (crr[i] > 0) {
            sum = sum + crr[i];
            sum2++;
        }
        else {
            sum2 = 0;
            sum = 0;
        }
        if (sum2 > k) {
            sum2--;
            sum = sum - crr[i - k];
        }
        ans = max(ans, sum);
    }
    cout << ans;

}

 D-Attribute Checks

思路

比较熟悉的dp题,

首先看到m的范围就得去想可能是m^2的复杂度,然后就是遍历到一个0时去思考会发生什么了,我们记录遍历到的0是第sum个0,那么之前遍历到的就是sum-1个0,我们定义dpxy为智力为x,另一个为y的最优解,那么我们从上一个0遍历到当前0时就会加个0,也就是变成了x+y+1,那么对于之前的0的之前的数,我们已经统计过了,现在就是两个0之间的数了,实际上就是前面状态如果到达x,那么现在两个0之间的小于x的数字都是答案,y同理,前缀和优化即可

代码

void solve() {
    ll n, m;
    cin >> n >> m;
    vectorarr(n + 2);
    vector>dp(m + 2, vector(m + 2));
    vectordp1(m + 2);
    vectordp2(m + 2);
    for (int i = 1; i <= n; i++) {
        cin >> arr[i];
    }
    ll sum = 0;
    ll sum2 = 0;
    ll ans = 0;
    for (int i = 1; i <= n+1; i++) {
        ll maxx = 0;
        
        if (arr[i] == 0) {
            
            sum++;
            for (int j = 1; j <= m; j++) {
                dp1[j] = dp1[j - 1] + dp1[j];
                dp2[j] = dp2[j - 1] + dp2[j];
                
            }
            for (int j = 0; j <= sum; j++) {
                if (j >= 1) {
                    dp[j][sum - j] = max(dp[j][sum - j], dp[j - 1][sum - j] + dp1[j - 1] + dp2[sum - j ]);
                }
                if (sum - j >= 1) {
                    dp[j][sum - j] = max(dp[j][sum - j], dp[j][sum - j - 1] + dp2[sum - j - 1] + dp1[j]);
                }
                
                maxx = max(maxx, dp[j][sum - j]);
            }
            for (int j = 0; j <= m; j++) {
                dp1[j] = 0;
                dp2[j] = 0;
            }
            
        }
        else if (arr[i] > 0) {
            dp1[arr[i]]++;
            sum2 = 0;
        }
        else {
            ll x = abs(arr[i]);
            dp2[x]++;
            sum2 = 0;
        }
        
    }
    m++;
    for (int i = 0; i <= m; i++) {
        ans = max(ans, dp[i][m - i]);
    }
    cout << ans;
    
}

 

你可能感兴趣的:(算法)