Digit Sum 2:
如果 N N 除了最高位全是 答案就是 N N 的数位和,否则让 最高位减 1 1 其他位全是 。
#include <bits/stdc++.h>
using namespace std;
#define X first
#define Y second
#define mp make_pair
#define pb push_back
#define Debug(...) fprintf(stderr, __VA_ARGS__)
typedef long long LL;
typedef long double LD;
typedef unsigned int uint;
typedef pair <int, int> pii;
typedef unsigned long long uLL;
template <typename T> inline void Read(T &x) {
char c = getchar();
bool f = false;
for (x = 0; !isdigit(c); c = getchar()) {
if (c == '-') {
f = true;
}
}
for (; isdigit(c); c = getchar()) {
x = x * 10 + c - '0';
}
if (f) {
x = -x;
}
}
template <typename T> inline bool CheckMax(T &a, const T &b) {
return a < b ? a = b, true : false;
}
template <typename T> inline bool CheckMin(T &a, const T &b) {
return a > b ? a = b, true : false;
}
int main() {
#ifdef wxh010910
freopen("d.in", "r", stdin);
#endif
char s[20];
scanf("%s", s);
bool flg = true;
for (int i = 1; i < strlen(s); ++i) {
if (s[i] != '9') {
flg = false;
break;
}
}
if (flg) {
int sum = 0;
for (int j = 0; j < strlen(s); ++j) {
sum += s[j] - '0';
}
printf("%d\n", sum);
} else {
printf("%d\n", strlen(s) * 9 + s[0] - '0' - 10);
}
#ifdef wxh010910
Debug("My Time: %.3lfms\n", (double)clock() / CLOCKS_PER_SEC);
#endif
return 0;
}
Holes:
对于每个 i i 分别求,枚举 ,做 (Pi,Pj) ( P i , P j ) 的垂直平分线,限制就是在直线某一侧。
注意到 R R 非常大,可以平移所有直线到原点。
#include <bits/stdc++.h>
using namespace std;
#define X first
#define Y second
#define mp make_pair
#define pb push_back
#define Debug(...) fprintf(stderr, __VA_ARGS__)
typedef long long LL;
typedef long double LD;
typedef unsigned int uint;
typedef pair <int, int> pii;
typedef unsigned long long uLL;
template <typename T> inline void Read(T &x) {
char c = getchar();
bool f = false;
for (x = 0; !isdigit(c); c = getchar()) {
if (c == '-') {
f = true;
}
}
for (; isdigit(c); c = getchar()) {
x = x * 10 + c - '0';
}
if (f) {
x = -x;
}
}
template <typename T> inline bool CheckMax(T &a, const T &b) {
return a < b ? a = b, true : false;
}
template <typename T> inline bool CheckMin(T &a, const T &b) {
return a > b ? a = b, true : false;
}
const int N = 105;
const double pi = acos(-1);
int n, m, b[N << 1];
double a[N << 1];
pii p[N];
inline double Fix(double x) {
if (x < 0) {
x += 2 * pi;
}
if (x >= 2 * pi) {
x -= 2 * pi;
}
return x;
}
int main() {
#ifdef wxh010910
freopen("d.in", "r", stdin);
#endif
Read(n);
for (int i = 1; i <= n; ++i) {
Read(p[i].X), Read(p[i].Y);
}
for (int i = 1; i <= n; ++i) {
m = 0;
for (int j = 1; j <= n; ++j) {
if (i == j) {
continue;
}
double l = atan2(p[j].Y - p[i].Y, p[j].X - p[i].X) - pi / 2, r = l + pi;
l = Fix(l), r = Fix(r);
a[++m] = l, a[++m] = r;
}
sort(a + 1, a + m + 1), m = unique(a + 1, a + m + 1) - a - 1;
for (int j = 1; j <= m; ++j) {
b[j] = 0;
}
for (int j = 1; j <= n; ++j) {
if (i == j) {
continue;
}
double l = atan2(p[j].Y - p[i].Y, p[j].X - p[i].X) - pi / 2, r = l + pi;
l = Fix(l), r = Fix(r);
int u = lower_bound(a + 1, a + m + 1, l) - a, v = lower_bound(a + 1, a + m + 1, r) - a;
for (int x = u; x != v; b[x] = 1, x = x % m + 1);
}
double len = 0;
for (int j = 1; j <= m; ++j) {
if (!b[j]) {
if (j == m) {
len += Fix(a[1] - a[m]);
} else {
len += Fix(a[j + 1] - a[j]);
}
}
}
printf("%lf\n", len / pi / 2);
}
#ifdef wxh010910
Debug("My Time: %.3lfms\n", (double)clock() / CLOCKS_PER_SEC);
#endif
return 0;
}
Tiling:
尽量用 个 A A 或者 个 B B 的去覆盖,注意特判 (N,M,A,B)=(3,3,2,2) ( N , M , A , B ) = ( 3 , 3 , 2 , 2 ) 的情况。
#include <bits/stdc++.h>
using namespace std;
#define X first
#define Y second
#define mp make_pair
#define pb push_back
#define Debug(...) fprintf(stderr, __VA_ARGS__)
typedef long long LL;
typedef long double LD;
typedef unsigned int uint;
typedef pair <int, int> pii;
typedef unsigned long long uLL;
template <typename T> inline void Read(T &x) {
char c = getchar();
bool f = false;
for (x = 0; !isdigit(c); c = getchar()) {
if (c == '-') {
f = true;
}
}
for (; isdigit(c); c = getchar()) {
x = x * 10 + c - '0';
}
if (f) {
x = -x;
}
}
template <typename T> inline bool CheckMax(T &a, const T &b) {
return a < b ? a = b, true : false;
}
template <typename T> inline bool CheckMin(T &a, const T &b) {
return a > b ? a = b, true : false;
}
const int N = 1005;
int n, m, a, b;
char s[N][N];
inline void A(int x, int y) {
if (a) {
s[x][y] = '<', s[x][y + 1] = '>', --a;
}
}
inline void B(int x, int y) {
if (b) {
s[x][y] = '^', s[x + 1][y] = 'v', --b;
}
}
int main() {
#ifdef wxh010910
freopen("d.in", "r", stdin);
#endif
Read(n), Read(m), Read(a), Read(b);
for (int i = 1; i <= n; ++i) {
for (int j = 1; j <= m; ++j) {
s[i][j] = '.';
}
}
if ((n & 1) && (m & 1) && n >= 3 && m >= 3) {
for (int i = 1; i < m; i += 2) {
A(n, i);
}
for (int i = 2; i < n; i += 2) {
B(i, m);
}
bool flg = false;
if (a & 1) {
A(1, m - 1), B(1, m - 2), flg = true;
}
for (int i = 1; i < n; i += 2) {
for (int j = 1; j < m; j += 2) {
if (i == 1 && j == m - 2 && flg) {
continue;
}
if (a) {
A(i, j), A(i + 1, j);
} else if (b) {
B(i, j), B(i, j + 1);
}
}
}
} else {
if (n & 1) {
for (int i = 1; i < m; i += 2) {
A(n, i);
}
}
if (m & 1) {
for (int i = 1; i < n; i += 2) {
B(i, m);
}
}
for (int i = 1; i < n; i += 2) {
for (int j = 1; j < m; j += 2) {
if (a) {
A(i, j), A(i + 1, j);
} else if (b) {
B(i, j), B(i, j + 1);
}
}
}
}
if (a || b) {
puts("NO");
} else {
puts("YES");
for (int i = 1; i <= n; ++i) {
for (int j = 1; j <= m; ++j) {
putchar(s[i][j]);
}
putchar(10);
}
}
#ifdef wxh010910
Debug("My Time: %.3lfms\n", (double)clock() / CLOCKS_PER_SEC);
#endif
return 0;
}
Reversed LCS:
不难发现如果没有修改答案就是最长回文子序列, f(l,r,k) f ( l , r , k ) 表示当前考虑区间 [l,r] [ l , r ] 允许改 k k 次的答案。
#include <bits/stdc++.h>
using namespace std;
#define X first
#define Y second
#define mp make_pair
#define pb push_back
#define Debug(...) fprintf(stderr, __VA_ARGS__)
typedef long long LL;
typedef long double LD;
typedef unsigned int uint;
typedef pair <int, int> pii;
typedef unsigned long long uLL;
template <typename T> inline void Read(T &x) {
char c = getchar();
bool f = false;
for (x = 0; !isdigit(c); c = getchar()) {
if (c == '-') {
f = true;
}
}
for (; isdigit(c); c = getchar()) {
x = x * 10 + c - '0';
}
if (f) {
x = -x;
}
}
template <typename T> inline bool CheckMax(T &a, const T &b) {
return a < b ? a = b, true : false;
}
template <typename T> inline bool CheckMin(T &a, const T &b) {
return a > b ? a = b, true : false;
}
const int N = 305;
int n, m, ans, f[N][N][N];
char s[N];
inline int Solve(int l, int r, int k) {
if (l >= r) {
return r - l + 1;
}
if (f[l][r][k]) {
return f[l][r][k];
}
f[l][r][k] = max(Solve(l + 1, r, k), Solve(l, r - 1, k));
if (s[l] == s[r]) {
CheckMax(f[l][r][k], Solve(l + 1, r - 1, k) + 2);
} else if (k) {
CheckMax(f[l][r][k], Solve(l + 1, r - 1, k - 1) + 2);
}
return f[l][r][k];
}
int main() {
#ifdef wxh010910
freopen("d.in", "r", stdin);
#endif
scanf("%s", s + 1), n = strlen(s + 1), Read(m);
for (int i = 1; i <= n; ++i) {
for (int j = i; j <= n; ++j) {
CheckMax(ans, Solve(i, j, m));
}
}
printf("%d\n", ans);
#ifdef wxh010910
Debug("My Time: %.3lfms\n", (double)clock() / CLOCKS_PER_SEC);
#endif
return 0;
}
Ball Eat Chameleons:
变色龙是红色的当且仅当它吃的红球比蓝球多,或者一样多且最后一个吃的是蓝球。
枚举红球个数 ,记蓝球个数为 B B ,把问题认为在二维平面上走,从 到 (R,B) ( R , B ) ,不难发现途中不能出现 y−x≥R−N+1 y − x ≥ R − N + 1 的情况,用类似卡特兰数的方法容斥一下就可以 O(1) O ( 1 ) 计算了。
#include <bits/stdc++.h>
using namespace std;
#define X first
#define Y second
#define mp make_pair
#define pb push_back
#define Debug(...) fprintf(stderr, __VA_ARGS__)
typedef long long LL;
typedef long double LD;
typedef unsigned int uint;
typedef pair <int, int> pii;
typedef unsigned long long uLL;
template <typename T> inline void Read(T &x) {
char c = getchar();
bool f = false;
for (x = 0; !isdigit(c); c = getchar()) {
if (c == '-') {
f = true;
}
}
for (; isdigit(c); c = getchar()) {
x = x * 10 + c - '0';
}
if (f) {
x = -x;
}
}
template <typename T> inline bool CheckMax(T &a, const T &b) {
return a < b ? a = b, true : false;
}
template <typename T> inline bool CheckMin(T &a, const T &b) {
return a > b ? a = b, true : false;
}
const int N = 500005;
const int mod = 998244353;
int n, m, ans, fac[N], inv[N];
inline int C(int x, int y) {
if (x < 0 || y < 0 || x < y) {
return 0;
}
return 1LL * fac[x] * inv[y] % mod * inv[x - y] % mod;
}
int main() {
#ifdef wxh010910
freopen("d.in", "r", stdin);
#endif
Read(n), Read(m), fac[0] = fac[1] = inv[0] = inv[1] = 1;
for (int i = 2; i <= m; ++i) {
fac[i] = 1LL * fac[i - 1] * i % mod;
inv[i] = 1LL * (mod - mod / i) * inv[mod % i] % mod;
}
for (int i = 2; i <= m; ++i) {
inv[i] = 1LL * inv[i - 1] * inv[i] % mod;
}
for (int i = n; i <= m; ++i) {
ans = (ans + C(m, i)) % mod;
ans = (ans - C(m, i * 2 - n + 1) + mod) % mod;
}
printf("%d\n", ans);
#ifdef wxh010910
Debug("My Time: %.3lfms\n", (double)clock() / CLOCKS_PER_SEC);
#endif
return 0;
}
Trinity:
记 f(i,j) f ( i , j ) 表示 i i 行 列的答案,且要求每行非空,则 ans=∑ni=0(ni)f(i,m) a n s = ∑ i = 0 n ( n i ) f ( i , m ) 。
考虑如何转移DP,每次新增一列,假设出现了 k k 行满足它们在 列第一次出现,那么就是 f(i,j)→f(i+k,j+1) f ( i , j ) → f ( i + k , j + 1 ) ,考虑如何计算系数。
k=0 k = 0 ,如果第 j+1 j + 1 列为空,则方案数为 1 1 , 否则是 的解数,为 (i+12) ( i + 1 2 ) 。
k>0 k > 0 ,那么放置完新增的 k k 行之后,可以在上面选择一个比放置的第一行更小的行作为列最小值,在下面选择一个比放置的最后一行更大的行作为列最大值,也可以不放。把最小值往上平移一个单位,最大值往下平移一个单位,然后认为它们也是新增的行,不难发现答案为 。
转移是卷积的形式,用FFT加速即可。
#include <bits/stdc++.h>
using namespace std;
#define X first
#define Y second
#define mp make_pair
#define pb push_back
#define Debug(...) fprintf(stderr, __VA_ARGS__)
typedef long long LL;
typedef long double LD;
typedef unsigned int uint;
typedef pair <int, int> pii;
typedef unsigned long long uLL;
template <typename T> inline void Read(T &x) {
char c = getchar();
bool f = false;
for (x = 0; !isdigit(c); c = getchar()) {
if (c == '-') {
f = true;
}
}
for (; isdigit(c); c = getchar()) {
x = x * 10 + c - '0';
}
if (f) {
x = -x;
}
}
template <typename T> inline bool CheckMax(T &a, const T &b) {
return a < b ? a = b, true : false;
}
template <typename T> inline bool CheckMin(T &a, const T &b) {
return a > b ? a = b, true : false;
}
const int N = 16385;
const int M = 15;
const int G = 3;
const int mod = 998244353;
namespace Polynomial {
int D, L, I[M], W[M], R[N];
inline int Qow(int x, int y) {
int r = 1;
for (; y; y >>= 1, x = 1LL * x * x % mod) {
if (y & 1) {
r = 1LL * r * x % mod;
}
}
return r;
}
inline int Inv(int x) {
return Qow(x, mod - 2);
}
inline void Ini(int l) {
for (D = 1, L = 0; D < l; D <<= 1, ++L);
for (int i = 1; i < D; ++i) {
R[i] = (R[i >> 1] >> 1) | ((i & 1) << L - 1);
}
W[0] = Qow(G, mod - 1 >> L), I[0] = Inv(W[0]);
for (int i = 1; i < L; ++i) {
W[i] = 1LL * W[i - 1] * W[i - 1] % mod;
I[i] = 1LL * I[i - 1] * I[i - 1] % mod;
}
}
inline void DFT(int *X, int *W) {
for (int i = 0; i < D; ++i) {
if (i < R[i]) {
swap(X[i], X[R[i]]);
}
}
for (int i = 1, l = L - 1; i < D; i <<= 1, --l) {
for (int j = 0; j < D; j += i << 1) {
for (int k = 0, w = 1, u, v; k < i; ++k, w = 1LL * w * W[l] % mod) {
u = X[j + k], v = 1LL * w * X[j + k + i] % mod;
X[j + k] = (u + v) % mod, X[j + k + i] = (u - v + mod) % mod;
}
}
}
}
}
using namespace Polynomial;
int n, m, ans, f[N], g[N], h[N], fac[N], inv[N];
inline int C(int x, int y) {
if (x < 0 || y < 0 || x < y) {
return 0;
}
return 1LL * fac[x] * inv[y] % mod * inv[x - y] % mod;
}
int main() {
#ifdef wxh010910
freopen("d.in", "r", stdin);
#endif
Read(n), Read(m), f[0] = fac[0] = fac[1] = inv[0] = inv[1] = 1;
for (int i = 2; i <= n + 2; ++i) {
fac[i] = 1LL * fac[i - 1] * i % mod;
inv[i] = 1LL * (mod - mod / i) * inv[mod % i] % mod;
}
for (int i = 2; i <= n + 2; ++i) {
inv[i] = 1LL * inv[i - 1] * inv[i] % mod;
}
Ini(n + 1 << 1);
int v = Inv(D);
for (int i = 1; i <= n; ++i) {
g[i] = inv[i + 2];
}
DFT(g, W);
for (int j = 1; j <= m; ++j) {
for (int i = 0; i < D; ++i) {
h[i] = i <= n ? 1LL * f[i] * inv[i] % mod : 0;
}
DFT(h, W);
for (int i = 0; i < D; ++i) {
h[i] = 1LL * h[i] * g[i] % mod;
}
DFT(h, I);
for (int i = 0; i <= n; ++i) {
f[i] = (1LL * h[i] * v % mod * fac[i + 2] + 1LL * f[i] * (C(i + 1, 2) + 1)) % mod;
}
}
for (int i = 0; i <= n; ++i) {
ans = (1LL * f[i] * C(n, i) + ans) % mod;
}
printf("%d\n", ans);
#ifdef wxh010910
Debug("My Time: %.3lfms\n", (double)clock() / CLOCKS_PER_SEC);
#endif
return 0;
}