目录
A Digits Sequence Dividing
B Digital root
C Brutality
D Compression
E Vasya and Binary String
给你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;
}
已经经过上述规则锁位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;
}
给你第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;
}
傻逼题意,比赛的时候完全模糊状态,他会给你一些压缩过的二进制编码,然后你需要对它进行解压,来获得一个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;
}
题意看了 , 只能想到2^(块数)的做法,给你一个01串,你可以任意消去连续的1、2、3等等个字符,并且删除i个连续的字符就可以获得下面对应的价值,让你求出最多可以获得多大的价值 。