B.Balanced Breakdown
-
题意 给定一个整数
n
n
n,需要你从中不断分离出回文数,使得
n
n
n最后变成
0
0
0,问需要最少的操作数,并输出方案。 -
解题思路 我们肯定是贪心构造当前
n
n
n能分离的最大回文数,那么如何构建呢?我们知道,对于回文数,其翻转过来和原来的数是相同的,则说明是回文数。我们可以截取
n
n
n的一半,那么再对其左半端减
1
1
1,就能保证右半段无论取什么构造出来的数都比
n
n
n小,然后倒过来累加右半段即可,具体看代码。 -
AC代码
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 100000 + 5;
const int P = 1e9+7;
ll n;
vector<ll> result;
ll cal(ll n){
if(n >= 11 && n <= 99)return n / 11 * 11;
string s = to_string(n);
string half = s;
reverse(half.begin(),half.end());
if(s == half)return n;
if(stoll(half) == 1){
return n - 1;
}
half = s.substr(0, s.size() + 1 >> 1);
half = to_string(stoll(half) - 1);
string ans = half;
int st = half.size() - 1 - s.size() % 2;
for(int i = st; i >= 0; -- i){
ans += half[i];
}
return stoll(ans);
}
void solve(){
while(n){
ll m = cal(n);
result.push_back(m);
n -= m;
}
cout << result.size() << endl;
for(ll &x : result){
cout << x << endl;
}
}
int main(){
cin >> n;
solve();
return 0;
}
C.Corrupted Contest
-
题意 有
n
n
n个人,然后
p
p
p道题,
t
i
t_i
ti?表示排名第
i
i
i的人做完最后一题的时间,若做题排序顺序唯一,求出每个人的做题排序顺序。 -
解题思路 我们知道,在同解题数的情况下,排名高的比排名低的时间要少。对于解题数为
0
0
0的,它们的罚时为
0
0
0。那么我们知道一点,如果做题顺序是唯一的,那么第一名一定解决了所有的题,否则从解决了第一个题到第一个都可以往前推一个档次,所以我们可以直接从做题数
p
p
p开始构造。 那么需要注意的就是,相邻两个人的做题数不能跨度超过
1
1
1,因为超过了也不能唯一确定。同时,如果最后一名的做题数不为
0
0
0,同样需要检测是否超过了
2
2
2,否则就可以通过做题数都减
1
1
1构造一个排序了。 -
AC代码
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 10000 + 5;
const int P = 1e9+7;
int n,p;
bool flag;
int t[N],ans[N];
void solve(){
for(int i = 1; i <= n; ++ i){
if(t[i] != 0 && p == 0){
flag = true;
}
if(t[i] == 0){
ans[i] = p = 0;
}
else if(t[i] >= t[i - 1]){
ans[i] = p;
}
else{
p --;
ans[i] = p;
}
if(p < 0)flag = true;
if(ans[i - 1] - ans[i] > 1){
flag = true;
}
}
if(flag || (ans[n] > 1 && t[n] != 0)){
printf("ambiguous\n");
}
else{
for(int i = 1; i <= n; ++ i){
printf("%d%c\n", ans[i], i == n ? '\n' : ' ');
}
}
}
int main(){
scanf("%d%d", &n, &p);
for(int i = 1; i <= n; ++ i){
scanf("%d", &t[i]);
}
solve();
return 0;
}
D.Efficiently Elevated
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const int N = 500 + 5;
const int P = 1e9+7;
struct node{
int x,y,z;
bool operator < (const node &A) const {
return z < A.z;
}
}nodes[N];
int n,m;
bool p[N][N];
priority_queue<node> q;
int a[N][N];
int go[4][2] = {0,1,0,-1,1,0,-1,0};
void dfs(int x,int y){
p[x][y] = 1;
for(int i = 0; i < 4; ++ i){
int dx = x + go[i][0],dy = y + go[i][1];
if(dx >= 1 && dx <= n && dy >= 1 && dy <= m && a[dx][dy] <= a[x][y] && !p[dx][dy]){
dfs(dx,dy);
}
}
}
void solve(){
int ans = 0;
while(!q.empty()){
node head = q.top();
q.pop();
if(!p[head.x][head.y]){
dfs(head.x,head.y);
ans ++;
}
}
printf("%d\n", ans);
}
int main(){
scanf("%d%d", &n, &m);
for(int i = 1; i <= n; ++ i){
for(int j = 1; j <= m; ++ j){
scanf("%d", &a[i][j]);
if(a[i][j] <= 1){
p[i][j] = 1;
}
else{
p[i][j] = 0;
q.push({i,j,a[i][j]});
}
}
}
solve();
return 0;
}
F.Generator Grid
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 200000 + 5;
const int P = 1e9+7;
struct edge{
int u,v,w;
bool operator < (const edge &A){
return w < A.w;
}
}edges[N];
int n,m,tot;
int father[N];
ll ans;
int find(int x){
int r = x;
while(father[r] != r){
r = father[r];
}
int i = x,j;
while(father[i] != r){
j = father[i];
father[i] = r;
i = j;
}
return r;
}
void solve(){
sort(edges + 1,edges + 1 + tot);
for(int i = 1; i <= n + 1; ++ i){
father[i] = i;
}
for(int i = 1; i <= tot; ++ i){
int fu = find(edges[i].u),fv = find(edges[i].v);
if(fu == fv)continue;
father[fu] = father[fv];
ans += edges[i].w;
}
printf("%lld\n", ans);
}
int main(){
scanf("%d%d", &n, &m);
int idx,w;
for(int i = 0; i < m; ++ i){
scanf("%d%d", &idx, &w);
edges[++tot] = {idx,n + 1,w};
}
for(int i = 1; i <= n; ++ i){
scanf("%d", &edges[++tot].w);
edges[tot].u = i;
if(i < n){
edges[tot].v = i + 1;
}
else{
edges[tot].v = 1;
}
}
solve();
return 0;
}
G.Hungry Henk
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 100 + 5;
const int P = 1e9+7;
int n;
string s;
vector<string> g[N];
bool vis[N];
bool flag;
void solve(){
int idx = 0;
for(int i = 1; i <= n; ++ i){
if(vis[i]){
idx = i;
break;
}
}
cout << g[idx].size() << endl;
for(auto &s : g[idx]){
cout << s << endl;
}
}
int main(){
cin >> n;
int x;
for(int i = 1; i <= n; ++ i){
cin >> x;
flag = false;
while(x -- ){
cin >> s;
if(s.size() > 20){
flag = true;
}
g[i].push_back(s);
}
if(!flag){
vis[i] = true;
}
}
solve();
return 0;
}
H.Incomplete Implementation
-
题意 给你
1
1
1~
n
n
n的排列数组,然后你可以每次任意选择n/2个不同的下标使得他们值排序,然后有序放回这几个位置,你最多有三次操作机请问你怎么操作,会使得这个乱序数组恢复有序。(可以输出仍以方式) -
解题思路 先排
[
n
/
4
?
3
+
1
,
n
]
[n/4*3+1,n]
[n/4?3+1,n]区间,再排
n
/
4
?
2
+
1
,
n
/
4
?
3
]
n/4*2+1,n/4*3]
n/4?2+1,n/4?3]区间,然后再排
[
1
,
n
/
2
]
[1,n/2]
[1,n/2]区间即可。怎么排呢?我们可以去寻找所在位置,然后利用原来位置和应该在的位置进行一次排序即可。 -
AC代码
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 100000 + 5;
const int P = 1e9+7;
int n,a[N],b[N];
int pos[N],vis[N];
void print(){
int cnt = 0;
for(int i = 1; i <= n; ++ i){
if(vis[i])cnt ++;
}
for(int i = 1; i <= n && cnt < n / 2; ++ i){
if(!vis[i]){
vis[i] = true;
cnt ++;
}
}
int sz = 0;
for(int i = 1; i <= n; ++ i){
if(vis[i]){
printf("%d ",i);
b[++ sz] = a[i];
}
}
sort(b + 1, b + sz + 1);
sz = 0;
for(int i = 1; i <= n; ++ i){
if(vis[i])a[i] = b[++ sz];
pos[a[i]] = i;
}
printf("\n");
memset(vis,false,sizeof(vis));
}
void solve(){
printf("3\n");
for(int i = n / 4 * 3 + 1; i <= n; ++ i){
vis[pos[i]] = true;
vis[i] = true;
}
print();
for(int i = n / 4 * 2 + 1; i <= n / 4 * 3; ++ i){
vis[pos[i]] = true;
vis[i] = true;
}
print();
for(int i = 1; i <= n / 2; ++ i){
vis[i] = true;
}
print();
}
int main(){
scanf("%d", &n);
for(int i = 1; i <= n; ++ i){
scanf("%d", &a[i]);
pos[a[i]] = i;
}
solve();
return 0;
}
I.Jigsaw
-
题意 给你
c
c
c个对角块,
e
e
e个边缘块,
m
m
m个中心块,问你能否拼成一个矩形。 -
解题思路 既然是对角,则必须满足
c
m
o
d
??
4
=
0
c\mod 4=0
cmod4=0,同时,由于有
e
e
e个边缘块,需要分成
2
2
2个长和宽,即
e
m
o
d
??
2
=
0
e\mod2=0
emod2=0,满足和这些条件之后,我们来假设去除对角和边缘形成的中间矩形长宽分别为
a
,
b
a,b
a,b,那么满足:
(
a
+
b
)
×
2
=
e
(a+b)\times 2=e
(a+b)×2=e
a
b
=
m
ab = m
ab=m 利用等式代换得到一元二次方程求解再测试解的合法性即可解决此题。 -
AC代码
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 100000 + 5;
const int P = 1e9+7;
int c,e,m;
void solve(){
if(c != 4 || e % 4 != 0){
cout << "impossible" << endl;
return;
}
int a1,a2,b1,b2;
a1 = (e + sqrt(1.0 * e * e - 16.0 * m)) / 4;
a2 = (e - sqrt(1.0 * e * e - 16.0 * m)) / 4;
b1 = e / 2 - a1;
b2 = e / 2 - a2;
if(a1 * b1 == m){
cout << a1 + 2 << " " << b1 + 2 << endl;
}
else if(a2 * b2 == m){
cout << a2 + 2 << " " << b2 + 2 << endl;
}
else{
cout << "impossible" << endl;
}
}
int main(){
cin >> c >> e >> m;
solve();
return 0;
}
|