2022 ICPC 济南区域赛题解 更新至 7 题(2022 International Collegiate Programming Contest, Jinan Site)
Preface
这场的C真的,让我脑细胞快死完了。
和张神推了快3个小时的dp,但是卡死在了最后的回退上。思考前后缀都无果,然后dp换了又换,最后终是燃尽了。
另外发现了个摸鱼G题。
我会在代码一些有必要的地方加上注释,签到题可能一般就不会写了.
以下是代码火车头:
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <vector>
#include <set>
#include <queue>
#include <map>
#include <unordered_map>
#include <iomanip>
#define endl '\n'
#define int long long
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
#define rep2(i,a,b) for(int i=(a);i>=(b);i--)
using namespace std;
template<typename T>
void cc(const vector<T> &tem) {
for (const auto &x: tem) cout << x << ' ';
cout << endl;
}
template<typename T>
void cc(const T &a) { cout << a << endl; }
template<typename T1, typename T2>
void cc(const T1 &a, const T2 &b) { cout << a << ' ' << b << endl; }
template<typename T1, typename T2, typename T3>
void cc(const T1 &a, const T2 &b, const T3 &c) { cout << a << ' ' << b << ' ' << c << endl; }
void cc(const string &s) { cout << s << endl; }
void fileRead() {
#ifdef LOCALL
freopen("D:\\AADVISE\\Clioncode\\untitled2\\in.txt", "r", stdin);
freopen("D:\\AADVISE\\Clioncode\\untitled2\\out.txt", "w", stdout);
#endif
}
void kuaidu() { ios::sync_with_stdio(false), cin.tie(0), cout.tie(0); }
inline int max(int a, int b) {
if (a < b) return b;
return a;
}
inline double max(double a, double b) {
if (a < b) return b;
return a;
}
inline int min(int a, int b) {
if (a < b) return a;
return b;
}
inline double min(double a, double b) {
if (a < b) return a;
return b;
}
void cmax(int &a, const int &b) { if (b > a) a = b; }
void cmin(int &a, const int &b) { if (b < a) a = b; }
void cmin(double &a, const double &b) { if (b < a) a = b; }
void cmax(double &a, const double &b) { if (b > a) a = b; }
using PII = pair<int, int>;
using i128 = __int128;
using vec_int = std::vector<int>;
using vec_char = std::vector<char>;
using vec_double = std::vector<double>;
using vec_int2 = std::vector<std::vector<int> >;
using que_int = std::queue<int>;
Problem A. Tower
也不知道哪个傻狗优先队列忘了清空WA了好几发。
这个题其实有点典,我们需要知道一个小trick,就是:如果一个数组里面,我们可以对任意一个数进行+1,或者-1的操作,问最少的操作次数变成同一个数字,那么最后变成的这个数字可以是他们中的中位数,这会是最少的操作次数之一。
那么加上/2的操作呢?
其实就是我们枚举的最终的数字的集合S里加上了每一个数字不停/2中间得到的数字,他们都有可能成为我们最终成为的数字。
这里的理解其实比较ez了,大概就是我们会先/2,/2,/2,然后再操作+和-的操作。如果我们一个数字先/2,再-1,-1,-1,再/2,其实不如我们/2,/2,再-1,-1这样快。
所以我们这里就把/2的操作转化成了枚举集合S。大小大概就是\(n*logn\),然后枚举每一个数字到达一个数字x,我们的复杂度有/2在,所以也是log级别的,复杂度就是\(n*log^2n\)。
//--------------------------------------------------------------------------------
const int N = 1e5 + 10;
const int M = 1e6 + 10;
const int mod = 1e9 + 7;
// const int mod = 998244353;
const int INF = 1e16;
auto kuai = Kuai<mod>;
int n, m, T;
int A[N];
//--------------------------------------------------------------------------------
//struct or namespace:
//--------------------------------------------------------------------------------
int to(int x, int mid) {
if (x == mid) return 0;
if (x < mid) return mid - x;
if ((x / 2) >= mid) return to(x / 2, mid) + 1;
return min(x - mid, ((mid - (x / 2)) + 1));
}
signed main() {
fileRead();
kuaidu();
T = 1;
cin >> T;
while (T--) {
cin >> n >> m;
rep(i, 1, n) cin >> A[i];
set<int> S;
rep(i, 1, n) {
int x = A[i];
while (x) {
if (S.count(x)) break;
S.insert(x);
x /= 2;
}
}
priority_queue<int, vec<int>, greater<int>> F;
int mmin = INF;
for (auto mid : S) {
while (!F.empty()) F.pop();
int ans = 0;
int sum = 0;
rep(i, 1, n) {
int tem = to(A[i], mid);
ans += tem;
F.push(tem);
sum += tem;
if (F.size() > m) {
sum -= F.top();
F.pop();
}
}
cmin(mmin, ans - sum);
}
cc(mmin);
}
return 0;
}
/*
*/
Problem C. DFS Order 2
这个题真的,让我好一阵领教。感觉更加的厌恶dp了。
中间若干很多推理的细节让我感觉非常的爽但是又很恶心。
首先我们需要理解一个叫回退背包的东西(可逆背包),但是其实我们可以换一个思路去理解,和回退背包相比,我觉得就是一个dp,只不过思路没有怎么考虑到过。
一个小问题:01背包的问题下,一个背包有n个物品,每个物品有重量,有q次查询,每次查询是排除了物品x,剩余的组成重量大小m的方案数(无序)是多少。
我们该怎么思考这个问题呢?其实也是一个dp。
我们先跑一遍正常的背包
倒序遍历后,这样\(dp[m]\)是我们的方案数。如何排除x呢?
设\(f[x][j]\)是排除了x物品,组成大小j的方案数量。
则有:
\(w\)是物品x的重量,为什么会有这个式子呢?
不妨考虑一下,原本来说,我们有重量j的所有的方案,现在想要取消x,dp[j]里有装了x的部分,和没有装x的部分,考虑dp[j]里已经装了物品x的部分,那么这一部分的方案数,其实是等价于排除了x,重量组成j-w的方案数的。(毕竟x固定了,剩下的重量就是j-w,而且还是没有x,那这一部分就对应的是排除了x,重量组成j-w的方案数)。
也就是说等价于我们的\(f[x][j-w]\),所以我们正序遍历,保证用于运算的值都计算出来过了。
我们就求出来了排除了x,组成大小为j的数组,也就是刚才这个问题的ans。
有些代码是直接在dp上面做文章,但是说实在的我脑子不是太灵光,只能有这种方式去理解,从无序什么的角度去考虑个人感觉不如这个直接写一个dp直观一些。
有了以上的前提,我们就可以开始做这个题了(阿巴竟然才开始)
首先我们要考虑一个dp[i][j],代表第i个点在第j个位置出现的次数。
假设对于每一个父亲x和儿子y来说,x的dp数组全部已知,然后他们中间间隔了k个点的方案数是已知的,那么我们就可以推出来dp[y]的值。
我们设置f[j][k]代表大小是j,选择了k个点的方案数(无序)。
通过倒序遍历得到之后,我们就得到了对于当前点x的大小是j,选择了k个点的方案数。
然后后续我们就可以对于每一个他的儿子y去跑一个ex[j][k]数组,定义和f一样,但是去掉了当前儿子y,做法是我们上文提到的dp。
然后得到了之后,我们还要再设一个数组g[j],代表大小是j的方案数是多少(有序),由于这个要考虑有序,所以我们还要考虑到k的阶乘,因为选择了k个点,我们还需要考虑他们之间的组合,所以要乘上k的阶乘,还有是去掉了当前这个点和前面的k个点,后面的剩余的点的阶乘。
到现在为止,这个g数组就是我们上文说的,间隔了k个点的方案数。
我们就可以写出来了这个式子。(sumx是x的儿子的个数)
x的方案数会有g[k-1]/(sum[x]!)分配到y的j里。
所以至此,按照我们上面说的内容,求出来dp数组,便是最后的答案了。
真的是一个又臭又长的dp啊。代码里有一点点的注释
//--------------------------------------------------------------------------------
const int N = 5e2 + 10;
const int M = 1e6 + 10;
// const int mod = 1e9 + 7;
const int mod = 998244353;
const int INF = 1e16;
auto kuai = Kuai<mod>;
int n, m, T;
//--------------------------------------------------------------------------------
//struct or namespace:
namespace nn {
const int N = 1e5 + 10;
vector<int> fact, infact;
void clear() {
fact.resize(N + 5);
infact.resize(N + 5);
fact[0] = infact[0] = 1;
for (int i = 1; i < N; i++) fact[i] = fact[i - 1] * i % mod;
infact[N - 1] = Kuai<mod>(fact[N - 1], mod - 2);
for (int i = N - 2; i >= 1; i--) {
infact[i] = infact[i + 1] * (i + 1) % mod;
}
}
int C(int n, int m) {
if (n < m or m < 0) return 0;
return fact[n] * infact[m] % mod * infact[n - m] % mod;
}
}
namespace z {
vector<PII> A[N];
int son[N], dep[N];
int val[N];
int f[N][N], g[N][N], sum[N];
int ex[N][N], dp[N][N];
void dfs(const int x, const int pa) {
son[x] = 1;
dep[x] = dep[pa] + 1;
val[x] = 1;
for (auto [y, _] : A[x]) {
if (y == pa) continue;
dfs(y, x);
son[x] += son[y];
val[x] *= val[y];
val[x] %= mod;
}
if (x != 1) sum[x] = A[x].size() - 1;
else sum[x] = A[x].size();
val[x] *= nn::fact[sum[x]];
val[x] %= mod;
}
void dfs2(int x, int pa) {
rep(i, 0, N - 1) rep(j, 0, N - 1) f[i][j] = 0;
//f[j][k]:大小是j,选择了k个点的方案数
f[0][0] = 1;
for (auto& [y, _] : A[x]) {
if (y == pa) continue;
rep2(j, son[x], son[y]) {
rep2(k, sum[x], 1) {
//val[x]:x的子树下的dfs序列的方案数
f[j][k] += f[j - son[y]][k - 1] % mod;
f[j][k] %= mod;
}
}
}
for (auto& [y, _] : A[x]) {
if (y == pa) continue;
rep(j, 0, n) {
rep(k, 0, n) {
ex[j][k] = 0;
}
}
rep(j, 0, son[x]) {
rep(k, 0, sum[x]) {
if (j >= son[y] and k >= 1) {
ex[j][k] += (f[j][k] - ex[j - son[y]][k - 1] + mod) % mod;
}
else {
ex[j][k] += f[j][k];
ex[j][k] %= mod;
}
//ex[j][k]:大小j,选择了k个点,除去了y当前这个点
ex[j][k] += mod, ex[j][k] %= mod;
}
}
static int ge[N];
rep(j, 0, n) ge[j] = 0;
rep(k, 0, sum[x] - 1) {
rep(j, 0, son[x]) {
ge[j] += ex[j][k] * nn::fact[k] % mod * nn::fact[sum[x] - 1 - k] % mod;
ge[j] %= mod;
}
}
rep(j, 1, n) {
rep(k, 1, j) {
dp[y][j] += dp[x][j - k] * ge[k - 1] % mod * nn::infact[sum[x]] % mod;
dp[y][j] %= mod;
}
}
}
for (auto& [y, _] : A[x]) {
if (y == pa) continue;
dfs2(y, x);
}
}
void clear(int n) {
rep(i, 1, n) {
A[i].clear();
}
}
void add(int x, int y, int c = 1) {
A[x].push_back({ y, c });
}
};
//--------------------------------------------------------------------------------
signed main() {
fileRead();
kuaidu();
T = 1;
//cin >> T;
while (T--) {
cin >> n;
z::clear(n);
nn::clear();
rep(i, 1, n - 1) {
int a, b; cin >> a >> b;
z::add(a, b);
z::add(b, a);
}
z::dfs(1, 0);
z::dp[1][1] = z::val[1];
z::dfs2(1, 0);
rep(i, 1, n) {
int sum = 0;
rep(j, 1, n) {
int tem = z::dp[i][j];
cout << tem << " ";
}
cout << endl;
}
}
return 0;
}
/*
*/
Problem D. Frozen Scoreboard
不是吧真的有人会写大模拟吗?
sorry我会补的
Problem E. Identical Parity
一个中规中矩的小推理题。
首先我们知道,最后一定是长成(n/k)个长度是k的一模一样的区间A,和最后的n%k的区间B(这个区间是要和前面的区间的前缀一样的)。
一模一样的原因是因为,我们需要保证任意长度是k的区间都是奇偶性一样,只考虑0,1,像滑动窗口那样,每一次右边进入的一个数字,奇偶性要和左边出去的数字一样,滑动k次,我们就能发现这一点。所以我们就说这个是一模一样(仅用0,1去考虑)。
首先如果k是偶数,直接1010101这样就可以了,答案是YES。
k是奇数的情况下,我们1的个数可能和0一样,也可能多1。这是后续分类讨论的点。
先说前提:区间A指的是这些一模一样的区间中的其中一个,区间B是最后n%k的 区间。
我们可以知道A里一定要么1多,要么0多,因为k是奇数。
我们如果假设1的个数是a,0的个数是b,暂定a>=b,那么我们如果要成立,起码需要保证\((a-b)*k<=|B|\)(B的长度)
这样我们才能够在B区间去补回来少的那些0。
所以会发现,这个a-b的差值,越少越好,所以我们就规定A区间里,1的个数比0的个数多1。(因为奇数的个数大于等于偶数的个数,所以就想着奇数比偶数多1,没考虑偶数比奇数多的情况)
然后我们假设,区间B里,1的个数是a,0的个数是b,则有:
只要这些式子都是满足的,那么就说明是YES,否则是No。
后面这两个不等式的判断是因为,我们需要保证最后的区间B是和区间A的前缀一样的,也就是说B是A的子集才可以。
//--------------------------------------------------------------------------------
const int N = 1e5 + 10;
const int M = 1e6 + 10;
const int mod = 1e9 + 7;
//const int mod = 998244353;
const int INF = 1e16;
auto kuai = Kuai<mod>;
int n, m, T;
//--------------------------------------------------------------------------------
//struct or namespace:
//--------------------------------------------------------------------------------
signed main() {
fileRead();
kuaidu();
T = 1;
cin >> T;
while (T--) {
int k;
cin >> n >> k;
if (k % 2 == 0) {
cc("Yes");
continue;
}
if (n == k) {
cc("Yes");
continue;
}
if (n % 2 == 0) {
if ((n / k) > (n % k)) {
cc("No");
continue;
}
}
else {
if ((n / k) - 1 > (n % k)) {
cc("No");
continue;
}
}
int c;
if (n % 2 == 1) c = n / k - 1;
else c = n / k;
if (((n % k) + c) % 2 == 0) {
int x, y;
y = ((n % k) + c) / 2;
x = y - c;
if (x <= ((k + 1) / 2) and y <= k / 2) {
cc("Yes");
}
else {
cc("No");
}
}
else {
cc("No");
continue;
}
}
return 0;
}
/*
*/
Problem G. Quick Sort
一个小弱智题,其实难度比C小好多,榜单歪了阿巴阿巴。
首先这个交换的复杂度是有些高的,如果每一次分出来的区间是1到n-1,n到n这种复杂度就会是\(O(n^2)\)。
我们考虑一下优化,找的时候,我们的i其实是在找(i,n)区间内的第一个大于等于val的下标,j其实是在找(1,j)区间内的最后一个小于等于val的下标。
典典线段树呀。
维护线段树的节点信息有mmax和mmin(区间最大值和区间最小值)。
我们仅考虑i的情况,j和他很类似。
首先,线段树的qry函数(x,l,r,l1,r1,k)
x是当前节点编号,l,r是当前节点的l和r,l1和r1是我们要查询的区间,k是查询的值。
qry函数查询失败会返回-1.
如果我们的左儿子的最大值都小于了k的话,我们就直接查询右儿子吧。
如果最大值是大于等于l的话,就代表左儿子是有希望的,去查询一下。如果查询成功了就返回坐标,如果失败了,我们就再到右儿子去查询一下。
这就是大体思路,剩下的看代码吧。
//--------------------------------------------------------------------------------
const int N = 5e5 + 10;
const int M = 1e6 + 10;
const int mod = 1e9 + 7;
//const int mod = 998244353;
const int INF = 1e16;
auto kuai = Kuai<mod>;
int n, m, T;
//--------------------------------------------------------------------------------
//struct or namespace:
class SEG {
#define xl x+x
#define xr x+x+1
//TODO 节点维护信息、apply函数、up函数
struct info {
int siz = 0;
int mmax = -INF;
int mmin = INF;
int lan = 0;
void apply(int k) {
// siz += k;
// mmax = k;
// mmin = k;
}
void modify(int k) {
siz = 1;
mmax = k;
mmin = k;
// mmin = k;
// you = 0;
// siz = 1;
// lan = 0;
}
friend info operator+(const info& q1, const info& q2) {
info q;
q.siz = q1.siz + q2.siz;
q.mmax = max(q1.mmax, q2.mmax);
q.mmin = min(q1.mmin, q2.mmin);
// q.mmin = min(q1.mmin, q2.mmin);
// if (q2.mmin == q1.mmin) q.you = min(q1.you, q2.you);
// else {
// if (q1.mmin < q2.mmin) q.you = q1.you;
// else q.you = q2.you;
// }
return q;
}
};
int L, R;
info F[unsigned(N * 2.7)];
void init(int x, int l, int r) {
if (l == r) {
F[x] = info();
return;
}
int mid = l + r >> 1;
init(xl, l, mid), init(xr, mid + 1, r);
F[x] = F[xl] + F[xr];
}
void down(int x) {
if (!F[x].lan) return;
F[xl].apply(F[x].lan), F[xr].apply(F[x].lan);
}
void add(int x, int l, int r, int l1, int r1, int k) {
if (l1 > r1) return;
if (l != r) down(x);
F[x].lan = 0;
if (l1 <= l and r <= r1) {
F[x].apply(k);
return;
}
int mid = l + r >> 1;
if (r1 <= mid) add(xl, l, mid, l1, r1, k);
else if (mid < l1) add(xr, mid + 1, r, l1, r1, k);
else add(xl, l, mid, l1, mid, k), add(xr, mid + 1, r, mid + 1, r1, k);
F[x] = F[xl] + F[xr];
}
void modi(int x, int l, int r, int pos, int k) {
if (pos < l or pos > r) return;
if (l != r) down(x);
F[x].lan = 0;
if (pos == l and pos == r) {
F[x].modify(k);
return;
}
int mid = l + r >> 1;
if (pos <= mid) modi(xl, l, mid, pos, k);
else modi(xr, mid + 1, r, pos, k);
F[x] = F[xl] + F[xr];
}
info qry(int x, int l, int r, int l1, int r1) {
if (l1 > r1) return info();
if (l != r) down(x);
F[x].lan = 0;
if (l1 <= l and r <= r1) return F[x];
int mid = l + r >> 1;
if (r1 <= mid) return qry(xl, l, mid, l1, r1);
else if (mid < l1) return qry(xr, mid + 1, r, l1, r1);
else { return qry(xl, l, mid, l1, mid) + qry(xr, mid + 1, r, mid + 1, r1); }
}
int get1(int x, int l, int r, int l1, int r1, int k) {
if (l1 > r1) return -1;
if (l == r) {
if (F[x].mmax >= k) return l;
else return -1;
}
int mid = l + r >> 1;
if (r1 <= mid) return get1(xl, l, mid, l1, r1, k);
else if (l1 >= mid + 1) return get1(xr, mid + 1, r, l1, r1, k);
else {
if (F[xl].mmax < k) return get1(xr, mid + 1, r, mid + 1, r1, k);
int pos = get1(xl, l, mid, l1, mid, k);
if (pos != -1) return pos;
else return get1(xr, mid + 1, r, mid + 1, r1, k);
// if (F[xl].mmax >= k) return get1(xl, l, mid, l1, mid, k);
// else
}
}
int get2(int x, int l, int r, int l1, int r1, int k) {
if (l1 > r1) return -1;
if (l == r) {
if (F[x].mmax <= k) return l;
else return -1;
}
int mid = l + r >> 1;
if (r1 <= mid) return get2(xl, l, mid, l1, r1, k);
else if (l1 >= mid + 1) return get2(xr, mid + 1, r, l1, r1, k);
else {
if (F[xr].mmin > k) return get2(xl, l, mid, l1, mid, k);
int pos = get2(xr, mid + 1, r, mid + 1, r1, k);
if (pos != -1) return pos;
else return get2(xl, l, mid, l1, mid, k);
// if (F[xl].mmax <= k) return get2(xr, mid + 1, r, mid + 1, r1, k);
// else return get2(xl, l, mid, l1, mid, k);
}
}
#undef xl
#undef xr
public:
void clear(int l, int r) {
L = l, R = r;
init(1, l, r);
}
void add(int l, int r, int k) {
cmax(l, L);
cmin(r, R);
add(1, L, R, l, r, k);
}
void modi(int pos, int k) { modi(1, L, R, pos, k); }
info qry(int l, int r) {
cmax(l, L);
cmin(r, R);
return qry(1, L, R, l, r);
}
int get1(int l, int r, int k) {
// cmax(l, L);
// cmin(r, R);
return get1(1, L, R, l, r, k);
}
int get2(int l, int r, int k) {
// cmax(l, L);
// cmin(r, R);
return get2(1, L, R, l, r, k);
}
} seg;
int A[N];
//--------------------------------------------------------------------------------
int ans = 0;
int ddd(int* A, int l, int r) {
int val = A[(l + r) / 2];
int i = l - 1, j = r + 1;
// int i = l, j = r;
while (1) {
// do {
// i++;
// } while (A[i] < val);
// do {
// j--;
// } while (A[j] > val);
// while (A[i] < val) i++;
// while (A[j] > val) j--;
i++, j--;
// cc(1, j, val);
i = seg.get1(i, n, val);
j = seg.get2(1, j, val);
// cc(j);
// if(j==-1)
// if(i==-1 or j==-1)
// cc(i, j, A[i], A[j]);
if (j == -1) return 0;
if (i == -1) return j;
if (i >= j) return j;
int q1 = seg.qry(i, i).mmax, q2 = seg.qry(j, j).mmax;
seg.modi(i, q2);
seg.modi(j, q1);
swap(A[i], A[j]);
ans++;
}
}
void dfs(int* A, int l, int r) {
if (l >= 0 and r >= 0 and l < r) {
int x = ddd(A, l, r);
dfs(A, l, x);
dfs(A, x + 1, r);
}
}
signed main() {
fileRead();
kuaidu();
T = 1;
cin >> T;
while (T--) {
cin >> n;
seg.clear(1, n);
ans = 0;
rep(i, 1, n) {
int a; cin >> a;
A[i] = a;
seg.modi(i, a);
}
// seg.modi(0, 0);
dfs(A, 1, n);
cc(ans);
}
return 0;
}
/*
5 9 9 1
9 8 9 2
1 8 4 2
2 5 8 1
3 4 6 3
4 3 6 3
1 2 2 1
2 1 2 1
2 2 2 2
5 8 8 4
6 7 7 5
7 6 7 5
4 5 6 4
5 4 6 4
5 6 6 5
6 5 6 5
7 7 7 7
*/
Problem K. Stack Sort
小弱智题,查询第i个数字要不要建stack只需要判断i+1有没有就好了。
//--------------------------------------------------------------------------------
const int N = 5e5 + 10;
const int M = 1e6 + 10;
const int mod = 1e9 + 7;
// const int mod = 998244353;
const int INF = 1e16;
auto kuai = Kuai<mod>;
int n, m, T;
int A[N];
bool fl[N];
//--------------------------------------------------------------------------------
//struct or namespace:
//--------------------------------------------------------------------------------
signed main() {
fileRead();
kuaidu();
T = 1;
cin >> T;
while (T--) {
cin >> n;
rep(i, 0, n + 5) fl[i] = 0;
int ans = 0;
rep(i, 1, n) {
cin >> A[i];
fl[A[i]] = 1;
if (fl[A[i] + 1] == 0) ans++;
}
cc(ans);
}
return 0;
}
/*
*/
Problem M. Best Carry Player
直接模拟就好了,但是写的有一点烂。
//--------------------------------------------------------------------------------
const int N = 1e5 + 10;
const int M = 1e6 + 10;
const int mod = 1e9 + 7;
// const int mod = 998244353;
const int INF = 1e16;
auto kuai = Kuai<mod>;
int n, m, T;
int A[N];
//--------------------------------------------------------------------------------
//struct or namespace:
//--------------------------------------------------------------------------------
signed main() {
fileRead();
kuaidu();
T = 1;
cin >> T;
while (T--) {
cin >> n;
rep(i, 1, n) cin >> A[i];
if (n == 1) {
cc(0);
continue;
}
int ans = 0;
int las = 0;
while (1) {
bool fl = 0;
int x = 0;
rep(i, 1, n) {
if (A[i] != 0) {
fl = 1;
x += A[i] % 10;
A[i] /= 10;
}
}
x += las;
ans += (x) / 10;
las = x / 10;
if (fl == 0) {
while (las) {
x = 0;
x += las;
ans += (x) / 10;
las = x / 10;
}
break;
}
}
cc(ans);
}
return 0;
}
/*
*/
PostScript
还是需要加训(吗?)
好懒,只想耍。没想到这学期比赛这么多,感觉拿一堆破铜烂铁回来给教练看,会gg。

浙公网安备 33010602011771号