Educational Codeforces Round 59 (Rated for Div. 2)

目录

 

A Digits Sequence Dividing

B Digital root

C Brutality

D Compression

E Vasya and Binary String

 


A Digits Sequence Dividing 

   给你n位的字符,然后让你分成后面的数严格大于前面的数的形式,思路很简单直接判断位数,分成两个,考虑4444这个情况,由于不爱测样例的我,被这个题的格式和换行卡了好多次,真恶心

代码如下:

#include 
#include 
using namespace std;

typedef long long ll;
typedef pair  P;
const int maxn = 5e6;
int  n,m;
bool vis[maxn];
struct node {
    int u,v,val;
} g[maxn];
bool cmp(struct node a, struct node b) {
    return a.val < b.val;
}
int fa[maxn];
int Find(int x) {
    if(x == fa[x]) return x;
    return fa[x] = Find(fa[x]);
}
int t;
int main() {
    int q;
    while(cin >> q) {
        while(q--) {
            cin >> n;
            string str;
            cin >> str;
            string cur ="";
            cur += str[0];
            string x = "";
            if(n == 1) {
                cout << "YES" << endl;
                cout << 1 << endl;
                cout << str[0] - '0' << " ";
                cout << endl;
                continue;
            }
            if(str[0] < str[1]) {
                cout << "YES" << endl;
                cout << 2 << endl;
                cout << str[0] << " ";
                for(int i = 1; i < n; i++) {
                    cout << str[i];
                }
                cout << endl;
                continue;
            } else {
                if(n == 2) {
                    cout << "NO" << endl;
                    continue;
                } else {
                    cout << "YES" << endl;
                    cout << 2 << endl;
                    cout << str[0] << " ";
                    for(int i = 1; i < n; i++) {
                        cout << str[i];
                    }
            cout << endl;
                    continue;
                }
            }
            cout << "NO" << endl;
        }
    }
    return 0;
}

B Digital root

     已经经过上述规则锁位k次的数x,让你求原来的数是多少,直接打表可得公式

   代码如下:

#include 
#include 
using namespace std;

typedef long long ll;
typedef pair  P;
const int maxn = 5e6;
int  n,m;
bool vis[maxn];
struct node {
    int u,v,val;
} g[maxn];
bool cmp(struct node a, struct node b) {
    return a.val < b.val;
}
int fa[maxn];
int Find(int x) {
    if(x == fa[x]) return x;
    return fa[x] = Find(fa[x]);
}
int t;
int main() {
    int q;
    ll k,x;
    while(cin >> q) {
            while(q--){
        cin >> k >> x;
        ll ans = (k - 1) * 9;
        cout << ans + x << endl;}
    }
    return 0;
}

C Brutality

    给你第i个位置敲击会获得的价值,并且要求同个字符不能连续敲击k次,让你求可以获得的最大价值,考虑连续字符的贡献怎么求,显然,可以放在一个优先队列当中,直接取前min(q.size(),k)即可

代码如下:


#include 
#include 
using namespace std;

typedef long long ll;
typedef pair  P;
const int maxn = 5e6;
bool vis[maxn];
struct node {
    int val;
    char c;
} g[maxn];
bool cmp(struct node a, struct node b) {
    return a.val > b.val;
}
int fa[maxn];
int Find(int x) {
    if(x == fa[x]) return x;
    return fa[x] = Find(fa[x]);
}
int a[maxn];
int t;
char str[maxn];
int s[maxn];
priority_queue, less > q;
int main() {
    ll n,k;
    while(cin >> n >> k) {
        memset(s,0,sizeof(s));
        for(int i = 1; i <= n; i++) cin >> a[i];
        scanf("%s",str + 1);
        mapm;
        ll ans = 0;
        ll num = 0;
        sets;
        char c = '#';
        for(int i = 1; i <= n; i++) {
            if(c != str[i]) {
                int numm = k;
//                cout << i << endl;
                while(!q.empty() && numm > 0) {
                    ans += q.top();
//                    cout << "ss "<< endl;
                    q.pop();
                    numm--;
                }
                while(!q.empty()) q.pop();
                m.clear();
                m[str[i]]++;
                c = str[i];
                q.push(a[i]);
//                cout << q.size() << endl;
            } else {
                c = str[i];
                q.push(a[i]);
                m[str[i]]++;
            }
//            cout << ans << " "  << i << endl;
        }
        int numm = k;
        while(!q.empty() && numm > 0) {
            ans += q.top();
            q.pop();
                    numm--;
        }
        cout << ans << endl;
    }
    return 0;
}

 

D Compression

傻逼题意,比赛的时候完全模糊状态,他会给你一些压缩过的二进制编码,然后你需要对它进行解压,来获得一个n * n 的二进制矩阵,对于每个矩阵可以满足  A[i][j]=B[⌈i/x⌉][⌈j/x⌉] , 写几个例子就可以发现,他是可以找到若干个矩阵,在边长为x的情况下,这个矩阵元素全部相同 ,则可以进行压缩,题目你问你可以压缩成最大边长多少的矩形。

那么我们可以枚举这个边长x , 由上面的公式可以知道,n一定是可以整除我们需要枚举的边长的,那么我们只要枚举n的因子,然后对于每个因子i,我们可以得到n / i  * (n / i)点,设为点集 S,那么怎么去check在S这个集合中,边长为i的矩阵是否满足可以压缩呢,这儿很简单 可以求一个矩阵的前缀和,然后算一下每个矩阵的面积,如果==0 或者 == i * i,证明当前矩阵中元素完全一致,并且如果S点集中所有矩阵都满足的话,便是可以压缩的,直接输出边长即可

代码如下:


#include 
#include 
using namespace std;

typedef long long ll;
typedef pair  P;
bool num[5250][5250];
int sum[5250][5250];
priority_queue, less > q;

int  get(char c) {
    int x;
    if(c >= 'A') x =  9 + (c - 'A') + 1;
    else  x = c - '0';
    return x;
}
int main() {
    ll n,k;
    ios::sync_with_stdio(false);
    while(cin >> n) {
        memset(num,0,sizeof(num));
        for(int i = 1; i <= n; i++) {
            string str;
            cin >> str;
            int cnt = 4 * str.size();
            for(int j = str.size() - 1; j >= 0; j--) {
                int x = get(str[j]), cur = 0;
                while(x) num[i][cnt--] = x % 2,x /= 2,cur++;
                while(cur < 4)  cnt--,cur++;
            }
        }
        memset(sum,0,sizeof(sum));
        for(int i = 1; i <= n; i++) {
            for(int j = 1; j <= n; j++) {
            sum[i][j] = sum[i - 1][j] + sum[i][j - 1] - sum[i - 1][j - 1] + num[i][j];
            }
        }
        for(int i = n;i >= 1;i--){
            if(n % i) continue;
            int flag = 1;
                        if(!flag) break;
            for(int j = 1;j <= n / i;j++){
                for(int k = 1;k <= n / i;k++){
                        if(!flag) break;
                    int s = sum[j * i][k * i] + sum[j * i - i][k * i - i] -sum[j * i][k * i - i] - sum[j * i - i][k * i];
                    if(s != 0 && s != i * i) flag = 0;
                }
            }
            if(flag){
                cout << i << endl;
                break;
            }
        }
//        printf("sdasd\n");
    }
    return 0;
}

E Vasya and Binary String

 题意看了 , 只能想到2^(块数)的做法,给你一个01串,你可以任意消去连续的1、2、3等等个字符,并且删除i个连续的字符就可以获得下面对应的价值,让你求出最多可以获得多大的价值 。

你可能感兴趣的:(Codeforces)