Educational Codeforces Round 59 (Rated for Div. 2) DE题解

Educational Codeforces Round 59 (Rated for Div. 2)

D. Compression

题目链接https://codeforces.com/contest/1107/problem/D

题意:

给出一个n*(n/4)的矩阵,这个矩阵原本是一些01矩阵,但是现在四个四个储存进二进制里面,现在给出的矩阵为0~9以及A~F,表示0~15。

然后问这个矩阵能否压缩为一个(n/x)*(n/x)的矩阵,满足原矩阵中大小为x*x的子矩阵所有数都相等(所有子矩阵构成整个原矩阵)。

题解:

我想的就是暴力,但题解似乎也是暴力,但题解的做法比我的做法要优美许多。我说说我的吧...

就是先看看横排能否压缩,找出所有能够压缩的v值,然后将v从大到小进行枚举,来看看列能否照样压缩,能就直接输出答案。

大体思路就是这样,但我写的代码比较复杂...其实对于将字符解码为二进制,用个二维数组就可以了...

题解的暴力就是直接几层循环枚举完事。

下面给出我的代码...

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 5205;
int n;
char s[N][N];
vector <int> vec;
int main(){
    scanf("%d",&n);
    for(int i=0;i<n;i++)
        scanf("%s",s[i]);
    for(int i=1;i<=n;i++){
        int flag=1;
        if(n%i!=0) continue ;
        for(int j=0;j<n;j++){
            if(strcmp(s[(j/i)*i],s[j])!=0){
                flag=0;
                break ;
            }
        }
        if(flag) vec.push_back(i);
    }
    reverse(vec.begin(),vec.end());
    int flag;
    for(auto v:vec){
        flag=1;
        for(int i=0;i<n;i+=v){
            vector <int> a;
            for(int j=0;j<n/4;j++){
                char c = s[i][j];
                int now;
                if(c>=‘A‘ && c<=‘F‘) now=c-‘A‘+10;
                else now=c-‘0‘;
                for(int k=3;k>=0;k--){
                    if((1<<k)&now) a.push_back(1);
                    else a.push_back(0);
                }
            }
            for(int k=0;k<n;k++){
                if(a[(k/v)*v]-‘0‘!=a[k]-‘0‘){
                    flag=0;
                    break ;
                }
            }
            if(!flag)  break ;
        }
        if(flag){
            cout<<v;
            return 0;
        }
    }
    return 0;
}

E. Vasya and Binary String

题目链接:https://codeforces.com/contest/1107/problem/E

题意:

给出一个01串,然后对这个串进行压缩,将长度为1,2....n的相同字符进行压缩会得到相应的权值。问怎样压缩可以得到最大的值。

题解:

这题考虑dp,因为压缩只有两种情况,要么压缩一个,要么压缩多个,这个压缩多个可以连续,也可以中间有间隔。

dp(i,j,k)表示起点为i,终点为j,压缩k个和si相同的字符所得到的最大代价。

转移的话就有两种:

1.dp(i,j,1)=max{dp(i+1,j,p)}+a[1];

2.dp(i,j,k)=max{dp(i+1,pos-1,p)}+dp(pos,j,k-1)-ak-1+ak.

这里面的max我是直接枚举得到最大值,然后dp的过程中枚举pos来进行转移。

详细见代码吧:

#include <bits/stdc++.h>
#define INF 0x3f3f3f3f
using namespace std;
typedef long long ll;
const int N = 105;
ll a[N];
ll dp[N][N][N];
char s[N];
int n;
int main(){
    scanf("%d",&n);
    scanf("%s",s+1);
    for(int i=1;i<=n;i++) cin>>a[i];
    memset(dp,0,sizeof(dp));
    for(int i=1;i<=n;i++) dp[i][i][1]=a[1];
    for(int i=n-1;i>=1;i--){
        for(int j=i+1;j<=n;j++){
            for(int k=1;k<=j-i;k++)
            dp[i][j][1]=max(dp[i][j][1],dp[i+1][j][k]+a[1]);
            for(int q=i+1;q<=j;q++){
                ll tmp=0;
                if(s[q]!=s[i]) continue ;
                for(int p=1;p<=q-i-1;p++) tmp=max(tmp,dp[i+1][q-1][p]);
                for(int k=2;k<=j-i+1;k++){
                    if(dp[q][j][k-1]) dp[i][j][k]=max(dp[i][j][k],tmp+dp[q][j][k-1]-a[k-1]+a[k]);
                }
            }
        }
    }
    ll ans = 0;
    for(int i=1;i<=n;i++) ans=max(ans,dp[1][n][i]);
    cout<<ans;
    return 0;
}

原文地址:https://www.cnblogs.com/heyuhhh/p/10352756.html

时间: 2024-10-16 22:10:43

Educational Codeforces Round 59 (Rated for Div. 2) DE题解的相关文章

Educational Codeforces Round 59 (Rated for Div. 2) E 区间dp + 状态定义

https://codeforces.com/contest/1107/problem/E 题意 给出01字符串s(n<=100),相邻且相同的字符可以同时消去,一次性消去i个字符的分数是\(a[i]\),问消去s最多能得到多少分数 题解 实质是安排消去次序使得分数最大,第一步采取的行动是递归边界 因为只有01串,所以s被分成了一段一段,考虑段处理 预处理出一次性消去i个字符的最大分数\(f[i]\) 定义\(dp[l][r][cnt]\)为消去第l到第r段加上cnt个字符和第l段相同得到的最大

Educational Codeforces Round 59 (Rated for Div. 2) (前四题)

A. Digits Sequence Dividing(英文速读) 练习英语速读的题,我还上来昏迷一次....只要长度大于2那么一定可以等于2那么前面大于后面就行其他no 大于2的时候分成前面1个剩下后面一定是对的因为按照数字大小 代码 #include <bits/stdc++.h> using namespace std; int main() { ios::sync_with_stdio(0); cin.tie(0); cout.tie(0); int n; cin>>n;

Educational Codeforces Round 59 (Rated for Div. 2)

A.Digits Sequence Dividing 题意:给你一个1-9的数字字符串,把它划分成若干段(>=2)段,使其大小递增. 错误:当长度为2的时候没考虑 #include<cstdio> #include<cmath> #include<cstring> #include<cstdlib> #include<algorithm> #include<iostream> #include<map> using

Educational Codeforces Round 59 (Rated for Div. 2)(ABCD)

A. Digits Sequence Dividing 题意:给你一个数字串,只包含1-9,让你至少分成两段,使得每一段的数字大于前一段的数字: 解:对n特判,如果n为2,那么比较一下两个数字大小,如果n>2,那么就可以直接分成两部分,第一部分1个数字,剩下都为第二部分: #include <bits/stdc++.h> using namespace std; typedef long long ll; const int maxn=1e3+10; const int mod=9982

Educational Codeforces Round 57 (Rated for Div. 2) ABCDF题解

ZZ出题人写NTT写成ZZ了吧,全是998244353,不需要取模的东西强行取模搞得我以为答案很大想了好久(指B题) A.任意输出 \([l,r]\) 内的一组满足 \(x \mid y\) 的 \(x, y\) ,保证有答案 我输出了 \(\lfloor \frac{r}{l} \rfloor \times l\) 输出2l也行 int main() { int T; in, T; while (T--) { int l, r; in, l, r; out, l, ' ', r / l * l

Educational Codeforces Round 80 (Rated for Div. 2)部分题解

A. Deadline 题目链接 题目大意 给你\(n,d\)两个数,问是否存在\(x\)使得\(x+\frac{d}{x+1}\leq n\),其中\(\frac{d}{x+1}\)向上取整. 解题思路 方案一:利用均值不等式公式推导 \(x+\frac{d}{x+1}=x+1+\frac{d}{x+1}-1\geq2\sqrt{d}-1\) 所以 \(\min(x+\frac{x}{d+1})=2\sqrt{d}-1\) 因此去判断\(2\sqrt{d}-1\leq n\)是否成,即\(4\

Educational Codeforces Round 84 (Rated for Div. 2) A-E题解

A. Sum of Odd Integers 首先可以算出从1开始到第k个奇数之和.如果和大于n,则不可能存在k个奇数加和等于n,否则用n减去前k个奇数的和,这个差值若是偶数,直接加到最大的奇数上,就可以满足题意要求,否则输出no. 1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 int main(){ 5 int t; 6 cin>>t; 7 while(t--){ 8 ll n

Educational Codeforces Round 73 (Rated for Div. 2)

比赛链接:Educational Codeforces Round 73 (Rated for Div. 2) 官方题解:Educational Codeforces Round 73 Editorial A. 2048 Game 题意 如果一个只包含 \(2\) 的幂次的集合,问能否从中选择一些数使得和为 \(2048\). 思路 不断合并直到凑到 \(2048\). 代码 #include <bits/stdc++.h> using namespace std; int main() {

Educational Codeforces Round 36 (Rated for Div. 2)

Educational Codeforces Round 36 (Rated for Div. 2) F. Imbalance Value of a Tree You are given a tree T consisting of n vertices. A number is written on each vertex; the number written on vertex i is ai. Let's denote the function I(x,?y) as the differ