Educational CodeForces Round 1 (A~F) Solution

· · 个人记录

更好的阅读体验?

A. Tricky Sum

题意描述

给出一个 n,让你求出从 1n 的和,但是其中每当遇到一个数是 2 的整数次幂时,就要变加为减。

简要分析

我们可以先计算 1\sim n 的和使用等差数列求和公式 \frac{n\times(n+1)} 2,随后再减去两倍的 1 \sim 2^x的和,使用等比数列求和公式 \frac{k^{x + 1} - 1}{(k-1)}

时间复杂度 $O(T \log^2 n)$。 ### 代码实现 ```cpp #include <cstdio> #include <iostream> #include <algorithm> #include <cstring> #include <string> #include <cmath> #include <vector> #include <map> #include <unordered_map> #include <unordered_set> #include <queue> #include <stack> #include <set> using namespace std; typedef long long ll; const ll maxn = 1e5 + 7; const ll INF = 1e9 + 7, MOD = 998244353; inline ll read() { char cCc; ll xXx = 0, wWw = 1; while (cCc < '0' || cCc > '9') (cCc == '-') && (wWw = -wWw), cCc = getchar(); while (cCc >= '0' && cCc <= '9') xXx = (xXx << 1) + (xXx << 3) + (cCc ^ '0'), cCc = getchar(); xXx *= wWw; return xXx; } inline void write(ll xXx) { if (xXx < 0) putchar('-'), xXx = -xXx; if (xXx > 9) write(xXx / 10); putchar(xXx % 10 + '0'); } namespace FastIO { class FastIOBase { protected: #ifdef OPENIOBUF static const ll BUFSIZE=1<<22; char buf[BUFSIZE+1]; ll buf_p=0; #endif FILE *target; public: #ifdef OPENIOBUF virtual void flush()=0; #endif FastIOBase(FILE *f) : target(f) {} ~FastIOBase() = default; }; class FastOutput : public FastIOBase { #ifdef OPENIOBUF public: inline void flush() { fwrite(buf,1,buf_p,target),buf_p=0; } #endif protected: inline void __putc(char x) { #ifdef OPENIOBUF if(buf[buf_p++]=x,buf_p==BUFSIZE)flush(); #else putc(x, target); #endif } template<typename T> inline void __write(T x) { static char stk[64], *top; top = stk; if (x < 0) return __putc('-'), __write(-x); do *(top++) = x % 10, x /= 10; while (x); for (; top != stk; __putc(*(--top) + '0')); } public: FastOutput(FILE *f = stdout) : FastIOBase(f) {} #ifdef OPENIOBUF inline void setTarget(FILE *f) { this->flush(),target=f; } ~FastOutput(){ flush(); } #else inline void setTarget(FILE *f) { target = f; } #endif template<typename ...T> inline void writesp(const T &...x) { initializer_list<ll>{(this->operator<<(x), __putc(' '), 0)...}; } template<typename ...T> inline void writeln(const T &...x) { initializer_list<ll>{(this->operator<<(x), __putc('\n'), 0)...}; } inline FastOutput &operator<<(char x) { return __putc(x), *this; } inline FastOutput &operator<<(const char *s) { for (; *s; __putc(*(s++))); return *this; } inline FastOutput &operator<<(const string &s) { return (*this) << s.c_str(); } template<typename T, typename=typename enable_if<is_integral<T>::value>::type> inline FastOutput &operator<<(const T &x) { return __write(x), *this; } } cout; class FastInput : public FastIOBase { #ifdef OPENIOBUF public: inline void flush() { buf[fread(buf,1,BUFSIZE,target)]='\0',buf_p=0; } #endif protected: inline char __getc() { #ifdef OPENIOBUF if(buf_p==BUFSIZE) flush(); return buf[buf_p++]; #else return getc(target); #endif } public: #ifdef OPENIOBUF FastInput(FILE *f=stdin): FastIOBase(f){ buf_p=BUFSIZE; } inline void setTarget(FILE *f) { this->flush(),target=f; } #else FastInput(FILE *f = stdin) : FastIOBase(f) {} inline void setTarget(FILE *f) { target = f; } #endif inline char getchar() { return __getc(); } template<typename ...T> inline void read(T &...x) { initializer_list<ll>{(this->operator>>(x), 0)...}; } inline FastInput &operator>>(char &x) { while (isspace(x = __getc())); return *this; } template<typename T, typename=typename enable_if<is_integral<T>::value>::type> inline FastInput &operator>>(T &x) { static char ch, sym; x = sym = 0; while (isspace(ch = __getc())); if (ch == '-') sym = 1, ch = __getc(); for (; isdigit(ch); x = (x << 1) + (x << 3) + (ch ^ 48), ch = __getc()); return sym ? x = -x : x, *this; } inline FastInput &operator>>(char *s) { while (isspace(*s = __getc())); for (; !isspace(*s) && *s && ~*s; *(++s) = __getc()); return *s = '\0', *this; } inline FastInput &operator>>(string &s) { char str_buf[(1 << 8) + 1], *p = str_buf; char *const buf_end = str_buf + (1 << 8); while (isspace(*p = __getc())); for (s.clear(), p++;; p = str_buf) { for (; p != buf_end && !isspace(*p = __getc()) && *p && ~*p; p++); *p = '\0', s.append(str_buf); if (p != buf_end) break; } return *this; } } cin; } ll kissme(ll di, ll zhi) { if (!zhi)return 1ll; ll x = kissme(di, zhi >> 1); if (zhi & 1)return x * x * di; else return x * x; } void solve() { ll n; FastIO::cin >> n; ll sum = n * (n + 1) / 2; ll l = 0, r = 32; while (l <= r) { ll mid = (l + r) >> 1; ll x = kissme(2, mid); if (x <= n && x * 2 > n) { l = mid; break; } else if (x > n)r = mid - 1; else l = mid + 1; } sum -= 2 * (kissme(2, l + 1) - 1); FastIO::cout << sum << '\n'; } signed main() { ll T; FastIO::cin >> T; while (T--)solve(); return 0; } ``` ## B. Queries on a String ### 题意描述 给你一个字符串 $s$,有 $m$ 次操作。 每次操作给定三个数 $l_i,r_i,k_i$ 表示在 $[l_i,r_i]$ 区间内循环右移 $k_i$ 次。 输出 $m$ 次操作后的子串。 ### 简要分析 在区间 $[l_i,r_i]$ 内,若循环右移了 $r_i - l_i + 1$ 发现回到了原点。 于是循环右移 $k_i$ 次等价于循环右移 $k_i\mod {r_i - l_i + 1}$ 次。 模拟即可。 时间复杂度 $O(nm)$。 ### 代码实现 ```cpp #include <cstdio> #include <iostream> #include <algorithm> #include <cstring> #include <string> #include <cmath> #include <vector> #include <map> #include <unordered_map> #include <unordered_set> #include <queue> #include <stack> #include <set> using namespace std; typedef long long ll; const ll maxn = 1e5 + 7; const ll INF = 1e9 + 7, MOD = 998244353; inline ll read() { char cCc; ll xXx = 0, wWw = 1; while (cCc < '0' || cCc > '9') (cCc == '-') && (wWw = -wWw), cCc = getchar(); while (cCc >= '0' && cCc <= '9') xXx = (xXx << 1) + (xXx << 3) + (cCc ^ '0'), cCc = getchar(); xXx *= wWw; return xXx; } inline void write(ll xXx) { if (xXx < 0) putchar('-'), xXx = -xXx; if (xXx > 9) write(xXx / 10); putchar(xXx % 10 + '0'); } namespace FastIO { class FastIOBase { protected: #ifdef OPENIOBUF static const ll BUFSIZE=1<<22; char buf[BUFSIZE+1]; ll buf_p=0; #endif FILE *target; public: #ifdef OPENIOBUF virtual void flush()=0; #endif FastIOBase(FILE *f) : target(f) {} ~FastIOBase() = default; }; class FastOutput : public FastIOBase { #ifdef OPENIOBUF public: inline void flush() { fwrite(buf,1,buf_p,target),buf_p=0; } #endif protected: inline void __putc(char x) { #ifdef OPENIOBUF if(buf[buf_p++]=x,buf_p==BUFSIZE)flush(); #else putc(x, target); #endif } template<typename T> inline void __write(T x) { static char stk[64], *top; top = stk; if (x < 0) return __putc('-'), __write(-x); do *(top++) = x % 10, x /= 10; while (x); for (; top != stk; __putc(*(--top) + '0')); } public: FastOutput(FILE *f = stdout) : FastIOBase(f) {} #ifdef OPENIOBUF inline void setTarget(FILE *f) { this->flush(),target=f; } ~FastOutput(){ flush(); } #else inline void setTarget(FILE *f) { target = f; } #endif template<typename ...T> inline void writesp(const T &...x) { initializer_list<ll>{(this->operator<<(x), __putc(' '), 0)...}; } template<typename ...T> inline void writeln(const T &...x) { initializer_list<ll>{(this->operator<<(x), __putc('\n'), 0)...}; } inline FastOutput &operator<<(char x) { return __putc(x), *this; } inline FastOutput &operator<<(const char *s) { for (; *s; __putc(*(s++))); return *this; } inline FastOutput &operator<<(const string &s) { return (*this) << s.c_str(); } template<typename T, typename=typename enable_if<is_integral<T>::value>::type> inline FastOutput &operator<<(const T &x) { return __write(x), *this; } } cout; class FastInput : public FastIOBase { #ifdef OPENIOBUF public: inline void flush() { buf[fread(buf,1,BUFSIZE,target)]='\0',buf_p=0; } #endif protected: inline char __getc() { #ifdef OPENIOBUF if(buf_p==BUFSIZE) flush(); return buf[buf_p++]; #else return getc(target); #endif } public: #ifdef OPENIOBUF FastInput(FILE *f=stdin): FastIOBase(f){ buf_p=BUFSIZE; } inline void setTarget(FILE *f) { this->flush(),target=f; } #else FastInput(FILE *f = stdin) : FastIOBase(f) {} inline void setTarget(FILE *f) { target = f; } #endif inline char getchar() { return __getc(); } template<typename ...T> inline void read(T &...x) { initializer_list<ll>{(this->operator>>(x), 0)...}; } inline FastInput &operator>>(char &x) { while (isspace(x = __getc())); return *this; } template<typename T, typename=typename enable_if<is_integral<T>::value>::type> inline FastInput &operator>>(T &x) { static char ch, sym; x = sym = 0; while (isspace(ch = __getc())); if (ch == '-') sym = 1, ch = __getc(); for (; isdigit(ch); x = (x << 1) + (x << 3) + (ch ^ 48), ch = __getc()); return sym ? x = -x : x, *this; } inline FastInput &operator>>(char *s) { while (isspace(*s = __getc())); for (; !isspace(*s) && *s && ~*s; *(++s) = __getc()); return *s = '\0', *this; } inline FastInput &operator>>(string &s) { char str_buf[(1 << 8) + 1], *p = str_buf; char *const buf_end = str_buf + (1 << 8); while (isspace(*p = __getc())); for (s.clear(), p++;; p = str_buf) { for (; p != buf_end && !isspace(*p = __getc()) && *p && ~*p; p++); *p = '\0', s.append(str_buf); if (p != buf_end) break; } return *this; } } cin; } string s; ll m; signed main() { FastIO::cin >> s; FastIO::cin >> m; while (m--) { ll l, r, k; FastIO::cin >> l >> r >> k; ll len = r - l + 1; k %= len; string cur; for (ll i = r - k; i <= r - 1; i++) { cur += s[i]; } for (ll i = l - 1; i < r - k; i++)cur += s[i]; for (ll i = l - 1, k = 0; i <= r - 1; i++) s[i] = cur[k++]; } FastIO::cout << s << '\n'; return 0; } ``` ## C. Nearest vectors ### 题意描述 有 $n$ 个点,每个点表示原点到该点的向量,让你求出两个向量最小的夹角,仅输出向量的序号。 ### 简要分析 计算每个向量与 x 轴的夹角,使用 C++ 自带库函数 $atan(x,y)$ 计算,这里要处理负数角度的情况加上 $2\times \pi$ 即可。 结果保留并排序,枚举向量 $\mathbf{v_i},\mathbf{v_{i+1}}$ 取角度差的最小值即可。 注意到向量 $\mathbf{v_1}$ 与向量 $\mathbf{v_n}$ 也是相邻的不要忘记统计。 ### 代码实现 ```cpp #include <algorithm> #include <bitset> #include <complex> #include <deque> #include <exception> #include <fstream> #include <functional> #include <iomanip> #include <ios> #include <iosfwd> #include <iostream> #include <istream> #include <iterator> #include <limits> #include <list> #include <locale> #include <map> #include <memory> #include <new> #include <numeric> #include <ostream> #include <queue> #include <set> #include <sstream> #include <stack> #include <stdexcept> #include <streambuf> #include <string> #include <typeinfo> #include <utility> #include <valarray> #include <vector> #include <array> #include <atomic> #include <chrono> #include <condition_variable> #include <forward_list> #include <future> #include <initializer_list> #include <mutex> #include <random> #include <ratio> #include <regex> #include <scoped_allocator> #include <system_error> #include <thread> #include <tuple> #include <typeindex> #include <type_traits> #include <unordered_map> #include <unordered_set> using namespace std; typedef long long ll; const ll maxn = 1e5 + 7; const ll INF = 1e9 + 7, MOD = 998244353; inline ll read() { char cCc; ll xXx = 0, wWw = 1; while (cCc < '0' || cCc > '9') (cCc == '-') && (wWw = -wWw), cCc = getchar(); while (cCc >= '0' && cCc <= '9') xXx = (xXx << 1) + (xXx << 3) + (cCc ^ '0'), cCc = getchar(); xXx *= wWw; return xXx; } inline void write(ll xXx) { if (xXx < 0) putchar('-'), xXx = -xXx; if (xXx > 9) write(xXx / 10); putchar(xXx % 10 + '0'); } namespace FastIO { class FastIOBase { protected: #ifdef OPENIOBUF static const ll BUFSIZE=1<<22; char buf[BUFSIZE+1]; ll buf_p=0; #endif FILE *target; public: #ifdef OPENIOBUF virtual void flush()=0; #endif FastIOBase(FILE *f) : target(f) {} ~FastIOBase() = default; }; class FastOutput : public FastIOBase { #ifdef OPENIOBUF public: inline void flush() { fwrite(buf,1,buf_p,target),buf_p=0; } #endif protected: inline void __putc(char x) { #ifdef OPENIOBUF if(buf[buf_p++]=x,buf_p==BUFSIZE)flush(); #else putc(x, target); #endif } template<typename T> inline void __write(T x) { static char stk[64], *top; top = stk; if (x < 0) return __putc('-'), __write(-x); do *(top++) = x % 10, x /= 10; while (x); for (; top != stk; __putc(*(--top) + '0')); } public: FastOutput(FILE *f = stdout) : FastIOBase(f) {} #ifdef OPENIOBUF inline void setTarget(FILE *f) { this->flush(),target=f; } ~FastOutput(){ flush(); } #else inline void setTarget(FILE *f) { target = f; } #endif template<typename ...T> inline void writesp(const T &...x) { initializer_list<ll>{(this->operator<<(x), __putc(' '), 0)...}; } template<typename ...T> inline void writeln(const T &...x) { initializer_list<ll>{(this->operator<<(x), __putc('\n'), 0)...}; } inline FastOutput &operator<<(char x) { return __putc(x), *this; } inline FastOutput &operator<<(const char *s) { for (; *s; __putc(*(s++))); return *this; } inline FastOutput &operator<<(const string &s) { return (*this) << s.c_str(); } template<typename T, typename=typename enable_if<is_integral<T>::value>::type> inline FastOutput &operator<<(const T &x) { return __write(x), *this; } } cout; class FastInput : public FastIOBase { #ifdef OPENIOBUF public: inline void flush() { buf[fread(buf,1,BUFSIZE,target)]='\0',buf_p=0; } #endif protected: inline char __getc() { #ifdef OPENIOBUF if(buf_p==BUFSIZE) flush(); return buf[buf_p++]; #else return getc(target); #endif } public: #ifdef OPENIOBUF FastInput(FILE *f=stdin): FastIOBase(f){ buf_p=BUFSIZE; } inline void setTarget(FILE *f) { this->flush(),target=f; } #else FastInput(FILE *f = stdin) : FastIOBase(f) {} inline void setTarget(FILE *f) { target = f; } #endif inline char getchar() { return __getc(); } template<typename ...T> inline void read(T &...x) { initializer_list<ll>{(this->operator>>(x), 0)...}; } inline FastInput &operator>>(char &x) { while (isspace(x = __getc())); return *this; } template<typename T, typename=typename enable_if<is_integral<T>::value>::type> inline FastInput &operator>>(T &x) { static char ch, sym; x = sym = 0; while (isspace(ch = __getc())); if (ch == '-') sym = 1, ch = __getc(); for (; isdigit(ch); x = (x << 1) + (x << 3) + (ch ^ 48), ch = __getc()); return sym ? x = -x : x, *this; } inline FastInput &operator>>(char *s) { while (isspace(*s = __getc())); for (; !isspace(*s) && *s && ~*s; *(++s) = __getc()); return *s = '\0', *this; } inline FastInput &operator>>(string &s) { char str_buf[(1 << 8) + 1], *p = str_buf; char *const buf_end = str_buf + (1 << 8); while (isspace(*p = __getc())); for (s.clear(), p++;; p = str_buf) { for (; p != buf_end && !isspace(*p = __getc()) && *p && ~*p; p++); *p = '\0', s.append(str_buf); if (p != buf_end) break; } return *this; } } cin; } template<typename T> inline T Min(T x, T y) { return x < y ? x : y; } template<typename T> inline T Max(T x, T y) { return x > y ? x : y; } template<typename T> inline void Swap(T &x, T &y) { T t = x; x = y, y = t; } template<typename T> inline T Abs(T x) { return x < 0 ? -x : x; } inline ll gcd(ll a, ll b) { return !b ? a : gcd(b, a % b); } inline ll lcm(ll a, ll b) { return a / gcd(a, b) * b; } inline ll Pow(ll n, ll k) { if (k < 0)return 0; ll ret = 1, now = n; while (k > 0) { if (k & 1)ret *= now; now *= now; k /= 2; } return ret; } inline ll popcount(ll n) { ll ret = 0, u = n; while (u) { ret += u % 2; u /= 2; } return ret; } struct node { ll x, y, id; long double w; } p[maxn]; bool cmp(node a, node b) { return a.w < b.w; } const long double pi = acos(-1); signed main() { // freopen("code.in","r",stdin); // freopen("code.out","w",stdout); ll n; FastIO::cin >> n; for (ll i = 1; i <= n; i++) { FastIO::cin >> p[i].x >> p[i].y; p[i].w = atan2(p[i].x, p[i].y), p[i].id = i; if (p[i].w < 0)p[i].w += 2 * pi; } sort(p + 1, p + 1 + n, cmp); long double ans = p[1].w - p[n].w + 2 * pi; ll x = p[1].id, y = p[n].id; for (ll i = 1; i < n; i++) if (p[i + 1].w - p[i].w < ans) ans = p[i + 1].w - p[i].w, x = p[i].id, y = p[i + 1].id; FastIO::cout << x << ' ' << y << '\n'; return 0; } ``` ## D. Igor In the Museum ### 题意描述 给你一个 $n \times m$ 的矩形,$k$ 次询问。 每次询问给定 $x,y$,求出点 $(x,y)$ 所在的联通块内相邻 # 的个数。 (这里注意,# 的个数可以重复计算!) ### 简要分析 搜索即可,但注意没搜索过一个联通块就要记下来该联通块的答案,避免重复搜索。 时间复杂度 $O(nm)$。 ### 代码实现 ```cpp #include <cstdio> #include <iostream> #include <algorithm> #include <cstring> #include <string> #include <cmath> #include <vector> #include <map> #include <unordered_map> #include <unordered_set> #include <queue> #include <stack> #include <set> using namespace std; typedef long long ll; const ll maxn = 1e3 + 7; const ll INF = 1e9 + 7, MOD = 998244353; const ll dx[] = {-1, 0, 1, 0}, dy[] = {0, -1, 0, 1}; inline ll read() { char cCc; ll xXx = 0, wWw = 1; while (cCc < '0' || cCc > '9') (cCc == '-') && (wWw = -wWw), cCc = getchar(); while (cCc >= '0' && cCc <= '9') xXx = (xXx << 1) + (xXx << 3) + (cCc ^ '0'), cCc = getchar(); xXx *= wWw; return xXx; } inline void write(ll xXx) { if (xXx < 0) putchar('-'), xXx = -xXx; if (xXx > 9) write(xXx / 10); putchar(xXx % 10 + '0'); } namespace FastIO { class FastIOBase { protected: #ifdef OPENIOBUF static const ll BUFSIZE=1<<22; char buf[BUFSIZE+1]; ll buf_p=0; #endif FILE *target; public: #ifdef OPENIOBUF virtual void flush()=0; #endif FastIOBase(FILE *f) : target(f) {} ~FastIOBase() = default; }; class FastOutput : public FastIOBase { #ifdef OPENIOBUF public: inline void flush() { fwrite(buf,1,buf_p,target),buf_p=0; } #endif protected: inline void __putc(char x) { #ifdef OPENIOBUF if(buf[buf_p++]=x,buf_p==BUFSIZE)flush(); #else putc(x, target); #endif } template<typename T> inline void __write(T x) { static char stk[64], *top; top = stk; if (x < 0) return __putc('-'), __write(-x); do *(top++) = x % 10, x /= 10; while (x); for (; top != stk; __putc(*(--top) + '0')); } public: FastOutput(FILE *f = stdout) : FastIOBase(f) {} #ifdef OPENIOBUF inline void setTarget(FILE *f) { this->flush(),target=f; } ~FastOutput(){ flush(); } #else inline void setTarget(FILE *f) { target = f; } #endif template<typename ...T> inline void writesp(const T &...x) { initializer_list<ll>{(this->operator<<(x), __putc(' '), 0)...}; } template<typename ...T> inline void writeln(const T &...x) { initializer_list<ll>{(this->operator<<(x), __putc('\n'), 0)...}; } inline FastOutput &operator<<(char x) { return __putc(x), *this; } inline FastOutput &operator<<(const char *s) { for (; *s; __putc(*(s++))); return *this; } inline FastOutput &operator<<(const string &s) { return (*this) << s.c_str(); } template<typename T, typename=typename enable_if<is_integral<T>::value>::type> inline FastOutput &operator<<(const T &x) { return __write(x), *this; } } cout; class FastInput : public FastIOBase { #ifdef OPENIOBUF public: inline void flush() { buf[fread(buf,1,BUFSIZE,target)]='\0',buf_p=0; } #endif protected: inline char __getc() { #ifdef OPENIOBUF if(buf_p==BUFSIZE) flush(); return buf[buf_p++]; #else return getc(target); #endif } public: #ifdef OPENIOBUF FastInput(FILE *f=stdin): FastIOBase(f){ buf_p=BUFSIZE; } inline void setTarget(FILE *f) { this->flush(),target=f; } #else FastInput(FILE *f = stdin) : FastIOBase(f) {} inline void setTarget(FILE *f) { target = f; } #endif inline char getchar() { return __getc(); } template<typename ...T> inline void read(T &...x) { initializer_list<ll>{(this->operator>>(x), 0)...}; } inline FastInput &operator>>(char &x) { while (isspace(x = __getc())); return *this; } template<typename T, typename=typename enable_if<is_integral<T>::value>::type> inline FastInput &operator>>(T &x) { static char ch, sym; x = sym = 0; while (isspace(ch = __getc())); if (ch == '-') sym = 1, ch = __getc(); for (; isdigit(ch); x = (x << 1) + (x << 3) + (ch ^ 48), ch = __getc()); return sym ? x = -x : x, *this; } inline FastInput &operator>>(char *s) { while (isspace(*s = __getc())); for (; !isspace(*s) && *s && ~*s; *(++s) = __getc()); return *s = '\0', *this; } inline FastInput &operator>>(string &s) { char str_buf[(1 << 8) + 1], *p = str_buf; char *const buf_end = str_buf + (1 << 8); while (isspace(*p = __getc())); for (s.clear(), p++;; p = str_buf) { for (; p != buf_end && !isspace(*p = __getc()) && *p && ~*p; p++); *p = '\0', s.append(str_buf); if (p != buf_end) break; } return *this; } } cin; } int n, m, k, a[maxn][maxn], col[maxn][maxn], cn, ans[100010]; bool p[maxn][maxn]; string c; void dfs(ll x, ll y, ll co) { ans[cn] += a[x][y]; col[x][y] = co; for (ll i = 0; i < 4; i++) { ll xc = x + dx[i], yc = y + dy[i]; if (xc < 1 || yc < 1 || xc > n || yc > m || p[xc][yc] || col[xc][yc])continue; dfs(xc, yc, co); } } signed main() { FastIO::cin >> n >> m >> k; for (ll i = 1; i <= n; i++) { FastIO::cin >> c; c = ' ' + c; for (ll j = 1; j <= m; j++)p[i][j] = (c[j] == '*'); } for (ll i = 1; i <= n; i++) for (ll j = 1; j <= m; j++) for (ll k = 0; k < 4; k++) a[i][j] += p[i + dx[k]][j + dy[k]]; ll x, y; while (k--) { FastIO::cin >> x >> y; if (!col[x][y])cn++, dfs(x, y, cn); FastIO::cout << ans[col[x][y]] << '\n'; } return 0; } ``` ## E. Chocolate Bar ### 题意描述 给你一块有 $n \times m$ 小块的巧克力,但是你只想吃 $k$ 小块,所以你需要切巧克力。 你只能水平或竖直的切,每一次切割的花费是所切下来若干小块的巧克力的最大边长平方。 询问最小贡献。 ### 简要分析 考虑 dp。 $f_{i,j,k}$ 表示 $i \times j$ 的巧克力切割成 $k$ 小块的最小花费。 考虑递归转移,枚举横竖切那一条边。 时间复杂度 $O(nmk)$。 ### 代码实现 ```cpp // LUOGU_RID: 104252173 #include <cstdio> #include <iostream> #include <algorithm> #include <cstring> #include <string> #include <cmath> #include <vector> #include <map> #include <unordered_map> #include <unordered_set> #include <queue> #include <stack> #include <set> using namespace std; typedef long long ll; const ll maxn = 1e5 + 7; const ll INF = 1e9 + 7, MOD = 998244353; inline ll read() { char cCc; ll xXx = 0, wWw = 1; while (cCc < '0' || cCc > '9') (cCc == '-') && (wWw = -wWw), cCc = getchar(); while (cCc >= '0' && cCc <= '9') xXx = (xXx << 1) + (xXx << 3) + (cCc ^ '0'), cCc = getchar(); xXx *= wWw; return xXx; } inline void write(ll xXx) { if (xXx < 0) putchar('-'), xXx = -xXx; if (xXx > 9) write(xXx / 10); putchar(xXx % 10 + '0'); } namespace FastIO { class FastIOBase { protected: #ifdef OPENIOBUF static const ll BUFSIZE=1<<22; char buf[BUFSIZE+1]; ll buf_p=0; #endif FILE *target; public: #ifdef OPENIOBUF virtual void flush()=0; #endif FastIOBase(FILE *f) : target(f) {} ~FastIOBase() = default; }; class FastOutput : public FastIOBase { #ifdef OPENIOBUF public: inline void flush() { fwrite(buf,1,buf_p,target),buf_p=0; } #endif protected: inline void __putc(char x) { #ifdef OPENIOBUF if(buf[buf_p++]=x,buf_p==BUFSIZE)flush(); #else putc(x, target); #endif } template<typename T> inline void __write(T x) { static char stk[64], *top; top = stk; if (x < 0) return __putc('-'), __write(-x); do *(top++) = x % 10, x /= 10; while (x); for (; top != stk; __putc(*(--top) + '0')); } public: FastOutput(FILE *f = stdout) : FastIOBase(f) {} #ifdef OPENIOBUF inline void setTarget(FILE *f) { this->flush(),target=f; } ~FastOutput(){ flush(); } #else inline void setTarget(FILE *f) { target = f; } #endif template<typename ...T> inline void writesp(const T &...x) { initializer_list<ll>{(this->operator<<(x), __putc(' '), 0)...}; } template<typename ...T> inline void writeln(const T &...x) { initializer_list<ll>{(this->operator<<(x), __putc('\n'), 0)...}; } inline FastOutput &operator<<(char x) { return __putc(x), *this; } inline FastOutput &operator<<(const char *s) { for (; *s; __putc(*(s++))); return *this; } inline FastOutput &operator<<(const string &s) { return (*this) << s.c_str(); } template<typename T, typename=typename enable_if<is_integral<T>::value>::type> inline FastOutput &operator<<(const T &x) { return __write(x), *this; } } cout; class FastInput : public FastIOBase { #ifdef OPENIOBUF public: inline void flush() { buf[fread(buf,1,BUFSIZE,target)]='\0',buf_p=0; } #endif protected: inline char __getc() { #ifdef OPENIOBUF if(buf_p==BUFSIZE) flush(); return buf[buf_p++]; #else return getc(target); #endif } public: #ifdef OPENIOBUF FastInput(FILE *f=stdin): FastIOBase(f){ buf_p=BUFSIZE; } inline void setTarget(FILE *f) { this->flush(),target=f; } #else FastInput(FILE *f = stdin) : FastIOBase(f) {} inline void setTarget(FILE *f) { target = f; } #endif inline char getchar() { return __getc(); } template<typename ...T> inline void read(T &...x) { initializer_list<ll>{(this->operator>>(x), 0)...}; } inline FastInput &operator>>(char &x) { while (isspace(x = __getc())); return *this; } template<typename T, typename=typename enable_if<is_integral<T>::value>::type> inline FastInput &operator>>(T &x) { static char ch, sym; x = sym = 0; while (isspace(ch = __getc())); if (ch == '-') sym = 1, ch = __getc(); for (; isdigit(ch); x = (x << 1) + (x << 3) + (ch ^ 48), ch = __getc()); return sym ? x = -x : x, *this; } inline FastInput &operator>>(char *s) { while (isspace(*s = __getc())); for (; !isspace(*s) && *s && ~*s; *(++s) = __getc()); return *s = '\0', *this; } inline FastInput &operator>>(string &s) { char str_buf[(1 << 8) + 1], *p = str_buf; char *const buf_end = str_buf + (1 << 8); while (isspace(*p = __getc())); for (s.clear(), p++;; p = str_buf) { for (; p != buf_end && !isspace(*p = __getc()) && *p && ~*p; p++); *p = '\0', s.append(str_buf); if (p != buf_end) break; } return *this; } } cin; } ll f[55][55][55]; ll dfs(ll n, ll m, ll p) { if (n * m == p || p == 0)return 0; if (n > m)swap(n, m); if (f[n][m][p])return f[n][m][p]; ll smin = INF; for (ll i = 1; i <= n / 2; i++) for (ll j = 0; j <= p; j++) { ll ans = m * m + dfs(i, m, j) + dfs(n - i, m, p - j); smin = min(ans, smin); } for (ll i = 1; i <= m / 2; i++) for (ll j = 0; j <= p; j++) { ll ans = n * n + dfs(i, n, j) + dfs(m - i, n, p - j); smin = min(ans, smin); } return f[n][m][p] = smin; } void solve() { ll n, m, k; FastIO::cin >> n >> m >> k; FastIO::cout << dfs(n, m, k) << '\n'; } signed main() { // freopen("code.in", "r", stdin); // freopen("code.out", "w", stdout); ll T; FastIO::cin >> T; while (T--)solve(); return 0; } /* * code by zhangzuoxiang */ ``` ## F. Cut Length ### 题意描述 给定 $n$ 个点的任意多边形,给定 $m$ 条直线求直线在多边形内部距离,在边上也算如在内。 ### 简要分析 求出该直线与此多边形的所有交点,然后处在相邻两个交点间的线段便是其处于多边形内的部分。 因为 $n$ 只有 $1000$,我们完全可以枚举每一条线段来找到它与直线的交点。 很明显这些交点都在该直线上,那么我们把它们按照从直线的一段到另一端的顺序排序,然后就是找出第一个交点和第二个交点间的线段,第三个和第四个间的线段,以此类推。 这是理论上的算法。真正实现起来会发现有很多要处理的: #### bug 1 关于重合的边的问题。 明显,如果边与直线重合,该边是一定要计入的;于是我们单独开一个数组维护所有这样的边,然后将这样的边与上文所述线段求一个并即可。 #### bug 2 关于直线何时与边有交的问题 比如说直线与一个角相交,或是直线与边重合。 在处理这 bug2 的时候,最好把所有 $180^\circ$ 的角都删掉,不然可能会增加讨论量。 最终时间复杂度 $O(nm \log n)$,因为区间并是 $O(n \log n)$ 的。 ### 代码实现 ```cpp #include <algorithm> #include <bitset> #include <complex> #include <deque> #include <exception> #include <fstream> #include <functional> #include <iomanip> #include <ios> #include <iosfwd> #include <iostream> #include <istream> #include <iterator> #include <limits> #include <list> #include <locale> #include <map> #include <memory> #include <new> #include <numeric> #include <ostream> #include <queue> #include <set> #include <sstream> #include <stack> #include <stdexcept> #include <streambuf> #include <string> #include <typeinfo> #include <utility> #include <valarray> #include <vector> #include <array> #include <atomic> #include <chrono> #include <condition_variable> #include <forward_list> #include <future> #include <initializer_list> #include <mutex> #include <random> #include <ratio> #include <regex> #include <scoped_allocator> #include <system_error> #include <thread> #include <tuple> #include <typeindex> #include <type_traits> #include <unordered_map> #include <unordered_set> using namespace std; typedef long long ll; const ll maxn = 2e3 + 7; const ll INF = 1e9 + 7, MOD = 998244353; inline void write(ll xXx) { if (xXx < 0) putchar('-'), xXx = -xXx; if (xXx > 9) write(xXx / 10); putchar(xXx % 10 + '0'); } namespace FastIO { class FastIOBase { protected: #ifdef OPENIOBUF static const ll BUFSIZE=1<<22; char buf[BUFSIZE+1]; ll buf_p=0; #endif FILE *target; public: #ifdef OPENIOBUF virtual void flush()=0; #endif FastIOBase(FILE *f) : target(f) {} ~FastIOBase() = default; }; class FastOutput : public FastIOBase { #ifdef OPENIOBUF public: inline void flush() { fwrite(buf,1,buf_p,target),buf_p=0; } #endif protected: inline void __putc(char x) { #ifdef OPENIOBUF if(buf[buf_p++]=x,buf_p==BUFSIZE)flush(); #else putc(x, target); #endif } template<typename T> inline void __write(T x) { static char stk[64], *top; top = stk; if (x < 0) return __putc('-'), __write(-x); do *(top++) = x % 10, x /= 10; while (x); for (; top != stk; __putc(*(--top) + '0')); } public: FastOutput(FILE *f = stdout) : FastIOBase(f) {} #ifdef OPENIOBUF inline void setTarget(FILE *f) { this->flush(),target=f; } ~FastOutput(){ flush(); } #else inline void setTarget(FILE *f) { target = f; } #endif template<typename ...T> inline void writesp(const T &...x) { initializer_list<ll>{(this->operator<<(x), __putc(' '), 0)...}; } template<typename ...T> inline void writeln(const T &...x) { initializer_list<ll>{(this->operator<<(x), __putc('\n'), 0)...}; } inline FastOutput &operator<<(char x) { return __putc(x), *this; } inline FastOutput &operator<<(const char *s) { for (; *s; __putc(*(s++))); return *this; } inline FastOutput &operator<<(const string &s) { return (*this) << s.c_str(); } template<typename T, typename=typename enable_if<is_integral<T>::value>::type> inline FastOutput &operator<<(const T &x) { return __write(x), *this; } } cout; class FastInput : public FastIOBase { #ifdef OPENIOBUF public: inline void flush() { buf[fread(buf,1,BUFSIZE,target)]='\0',buf_p=0; } #endif protected: inline char __getc() { #ifdef OPENIOBUF if(buf_p==BUFSIZE) flush(); return buf[buf_p++]; #else return getc(target); #endif } public: #ifdef OPENIOBUF FastInput(FILE *f=stdin): FastIOBase(f){ buf_p=BUFSIZE; } inline void setTarget(FILE *f) { this->flush(),target=f; } #else FastInput(FILE *f = stdin) : FastIOBase(f) {} inline void setTarget(FILE *f) { target = f; } #endif inline char getchar() { return __getc(); } template<typename ...T> inline void read(T &...x) { initializer_list<ll>{(this->operator>>(x), 0)...}; } inline FastInput &operator>>(char &x) { while (isspace(x = __getc())); return *this; } template<typename T, typename=typename enable_if<is_integral<T>::value>::type> inline FastInput &operator>>(T &x) { static char ch, sym; x = sym = 0; while (isspace(ch = __getc())); if (ch == '-') sym = 1, ch = __getc(); for (; isdigit(ch); x = (x << 1) + (x << 3) + (ch ^ 48), ch = __getc()); return sym ? x = -x : x, *this; } inline FastInput &operator>>(char *s) { while (isspace(*s = __getc())); for (; !isspace(*s) && *s && ~*s; *(++s) = __getc()); return *s = '\0', *this; } inline FastInput &operator>>(string &s) { char str_buf[(1 << 8) + 1], *p = str_buf; char *const buf_end = str_buf + (1 << 8); while (isspace(*p = __getc())); for (s.clear(), p++;; p = str_buf) { for (; p != buf_end && !isspace(*p = __getc()) && *p && ~*p; p++); *p = '\0', s.append(str_buf); if (p != buf_end) break; } return *this; } } cin; } template<typename T> inline T Min(T x, T y) { return x < y ? x : y; } template<typename T> inline T Max(T x, T y) { return x > y ? x : y; } template<typename T> inline void Swap(T &x, T &y) { T t = x; x = y, y = t; } template<typename T> inline T Abs(T x) { return x < 0 ? -x : x; } inline ll gcd(ll a, ll b) { return !b ? a : gcd(b, a % b); } inline ll lcm(ll a, ll b) { return a / gcd(a, b) * b; } template<typename T> inline ll Pow(T n, ll k) { if (k < 0)return 0; T ret = 1, now = n; while (k) { if (k & 1)ret *= now; now *= now, k >>= 1; } return ret; } inline ll popcount(ll n) { ll ret = 0, u = n; while (u) ret += (u & 1), u >>= 1; return ret; } #define for_(i, a, b) for (ll i = (a); i < (b); i++) #define rep_(i, a, b) for (ll i = (a); i <= (b); i++) #define fi first #define se second #define sz(a) a.size() #define all(v) v.begin(), v.end() #define pb push_back #define DEBUG(x) cerr << #x << '=' << x << '\n' #define ccin FastIO::cin #define ccout FastIO::cout typedef unsigned long long ull; typedef double db; typedef long double ldb; const ldb EPS = 1e-9, pi = acos(-1); #define double long double const double eps = 1e-6; ll cmp(double x) { if (x > eps)return 1; if (x < -eps)return -1; return 0; } struct Vector { double x, y; Vector() {} Vector(double X, double Y) { x = X, y = Y; } friend Vector operator+(const Vector &u, const Vector &v) { return Vector(u.x + v.x, u.y + v.y); } friend Vector operator-(const Vector &u, const Vector &v) { return Vector(u.x - v.x, u.y - v.y); } friend Vector operator*(const Vector &u, const double &v) { return Vector(u.x * v, u.y * v); } friend Vector operator/(const Vector &u, const double &v) { return Vector(u.x / v, u.y / v); } friend double operator&(const Vector &u, const Vector &v) { return u.x * v.y - u.y * v.x; } friend double operator|(const Vector &u, const Vector &v) { return u.x * v.x + u.y * v.y; } double operator~() const { return sqrt(x * x + y * y); } double operator!() const { return atan2(y, x); } friend bool operator<(const Vector &u, const Vector &v) { return cmp(u.x - v.x) ? u.x < v.x : u.y < v.y; } friend bool operator==(const Vector &u, const Vector &v) { return !cmp(u.x - v.x) && !cmp(u.y - v.y); } void read() { scanf("%Lf%Lf", &x, &y); } void prll() const { printf("(%Lf,%Lf)", x, y); } } p[1010]; Vector read() { Vector x; x.read(); return x; } typedef Vector Poll; struct Line { Poll x, y; Vector z; Line() {} Line(Poll X, Poll Y) { x = X, y = Y, z = Y - X; } void prll() const { x.prll(), y.prll(); } friend Poll operator&(const Line &u, const Line &v) { return u.x + u.z * ((v.z & (u.x - v.x)) / (u.z & v.z)); } friend ll operator&(const Line &u, const Poll &v) { return cmp((v - u.x) & (v - u.y)); }//poll v is on which side of line u }; typedef Line Segment; ll n, m; vector<Segment> u; vector<Poll> v, w; vector<ll> b; bool on[1010]; double calc(Line l) { u.clear(), v.clear(), memset(on, false, sizeof(on)); for (ll i = 0; i < n; i++) { if (!cmp((p[i] - p[(i + 1) % n]) & l.z)) { if (cmp(l.z & (p[i] - l.x)))continue; u.emplace_back(p[i], p[(i + 1) % n]); Segment tmp(p[i], p[(i + 1) % n]); if ((tmp & p[(i + n - 1) % n]) != (tmp & p[(i + 2) % n]))v.push_back(p[i]); continue; } Poll x = Line(p[i], p[(i + 1) % n]) & l; if (x == p[i]) { on[i] = true; continue; } if (x == p[(i + 1) % n]) { on[(i + 1) % n] = true; continue; } if (cmp((x - p[i]) | (x - p[(i + 1) % n])) == 1)continue; v.push_back(x); } for (ll i = 0; i < n; i++) { if (!on[i])continue; if (on[(i + n - 1) % n] || on[(i + 1) % n])continue; Poll x = (l.x == p[i] ? l.y : l.x); Segment A(p[(i + n - 1) % n], p[i]); bool a = ((A & x) != (A & p[(i + 1) % n])); Segment B(p[(i + 1) % n], p[i]); bool b = ((B & x) != (B & p[(i + n - 1) % n])); if (a == b)v.push_back(p[i]); } sort(v.begin(), v.end()), w = v; for (auto i:u)w.push_back(i.x), w.push_back(i.y); sort(w.begin(), w.end()); b.assign(w.size(), 0); for (ll i = 0; i < v.size(); i += 2) { ll l = lower_bound(w.begin(), w.end(), v[i]) - w.begin(); ll r = lower_bound(w.begin(), w.end(), v[i + 1]) - w.begin(); b[l]++, b[r]--; } for (ll i = 0; i < u.size(); i++) { ll l = lower_bound(w.begin(), w.end(), u[i].x) - w.begin(); ll r = lower_bound(w.begin(), w.end(), u[i].y) - w.begin(); if (l > r)swap(l, r); b[l]++, b[r]--; } for (ll i = 1; i < b.size(); i++)b[i] += b[i - 1]; double ret = 0; for (ll i = 0; i + 1 < b.size(); i++)if (b[i])ret += ~(w[i + 1] - w[i]); return ret; } ll N; signed main() { scanf("%lld%lld", &N, &m); for (ll i = 0; i < N; i++) { p[n].read(); if (n >= 2 && cmp((p[n] - p[n - 1]) & (p[n] - p[n - 2])) == 0)n--, p[n] = p[n + 1]; n++; } if (n >= 3 && cmp((p[0] - p[n - 1]) & (p[0] - p[n - 2])) == 0)n--; if (n >= 3 && cmp((p[1] - p[0]) & (p[1] - p[n - 1])) == 0) { for (ll i = 0; i + 1 < n; i++)p[i] = p[i + 1]; n--; } while (m--)printf("%.10Lf\n", calc(Line(read(), read()))); return 0; } ``` ——$\mathscr{ClaudeZ.}