F. Rhyme scheme
题意:
给定n和k,要求输出长度为n的第k个Rhyme scheme。(1 ≤ n ≤ 26,1 ≤ k ≤ Bell Number(n) )
题解:
1、Bell(26) 的值为12737758376199653042,远远超过unsigned long long,我们可以使用__int128。
2、使用动态规划做,详细的看代码。
代码:
#include
#include
using namespace std;
const int N = 27;
int t, n, ans[N];
__int128 d[N][N][N], k;
void read (__int128 &x) {
x = 0;
char c = getchar();
while (c < '0' || c > '9') c = getchar();
for (; c <= '9' && c >= '0'; c = getchar()) {
x = x * 10 + c - '0';
}
}
void dp () {
for (int i = 0; i <= 25; i++) {
for (int j = 0; j <= 25; j++) {
d[25][i][j] = 1;
}
}
// 索引l
for (int l = 24; l >= 0; l--) {
// i为索引l的字母为 i + 'A'
for (int i = 0; i <= l; i++) {
// 父节点以及自己这个节点最大值为j
for (int j = 0; j <= l; j++) {
// k为自己的节点的子节点的值
d[l][i][j] = d[l+1][j+1][j+1];
for (int k = 0; k <= j; k++) {
d[l][i][j] += d[l+1][k][j];
}
}
}
}
}
void find (int cur, int i, int maxi) {
if (n == cur) return ;
for (int j = 0; j <= maxi; j++) {
if (d[i][j][maxi] >= k) {
ans[cur] = j;
find(cur + 1, i + 1, maxi);
return ;
}
k -= d[i][j][maxi];
}
ans[cur] = maxi + 1;
find(cur + 1, i + 1, maxi + 1);
}
int main () {
dp();
scanf("%d\n", &t);
for (int kase = 1; kase <= t; kase++) {
scanf("%d\n", &n); read(k);
find(0, 26 - n, 0);
printf("Case #%d: ", kase);
for (int i = 0; i < n; i++) {
printf("%c", ans[i] + 'A');
}
printf("\n");
}
return 0;
}
比赛上我写出的题目
B. Light bulbs
#include
#include
#include
#include
using namespace std;
const int M = 1010;
vector c;
int t, n, m, p[M*4], op[M][2];
int find (int x) {
int l = 0, r = c.size() - 1;
while (l < r) {
int mid = (l + r + 1) / 2;
if (c[mid] <= x) l = mid;
else r = mid - 1;
}
return l + 1;
}
int main () {
scanf("%d", &t);
for (int kase = 1; kase <= t; kase++) {
c.clear();
memset(p, 0, sizeof(p));
scanf("%d%d", &n, &m);
for (int i = 0; i < m; i++) {
scanf("%d%d", &op[i][0], &op[i][1]);
c.push_back(op[i][0]);
c.push_back(op[i][1]);
c.push_back(op[i][1]+1);
}
sort(c.begin(), c.end());
c.erase(unique(c.begin(), c.end()), c.end());
for (int i = 0; i < m; i++) {
int l = find(op[i][0]), r = find(op[i][1]);
p[l]++;
p[r+1]--;
}
for (int i = 1; i < c.size(); i++) {
p[i] = p[i-1] + p[i] ;
}
int ans = 0;
for (int i = 1; i < c.size(); i++) {
if (p[i] % 2 == 1) {
ans += c[i] - c[i-1];
}
}
printf("Case #%d: %d\n", kase, ans);
}
return 0;
}
D. Counting Sequences I
#include
using namespace std;
typedef long long ll;
const int N = 3010;
const int mod = 1e9 + 7;
int t, n, val = 1, cache = 0;
ll f[N];
int num[1000], cnt[1000], tot;
ll quickpow(ll a, ll b) {
if (b < 0) return 0;
ll ret = 1;
a %= mod;
while (b) {
if (b & 1) ret = (ret * a) % mod;
b >>= 1;
a = (a * a) % mod;
}
return ret;
}
ll inv(ll a) {
return quickpow(a, mod - 2);
}
ll A (int x, int y) {
ll val = 1;
for (int i = y - x + 1; i <= y; i++) {
val = (val * i) % mod;
}
return val;
}
void dfs (int cur, int i) {
if (cur + val - cache >= 2 && cur + val - cache <= 3000) {
ll ans = A(cur, cur + val - cache);
// if (cur + val - cache == 3000) {
// int z = 0;
// }
for (int j = 1; j <= tot; j++) {
ans = (ans * inv(A(cnt[j], cnt[j]))) % mod;
}
f[cur + val - cache] = (f[cur + val - cache] + ans) % mod;
}
if (i > 1 && cur + val * i - i - cache <= 6000) {
cache += i;
val = val * i;
cnt[tot]++;
dfs(cur + 1, i);
val = val / i;
cnt[tot]--;
cache -= i;
}
for (i = i + 1; i <= 3000; i++) {
num[++tot] = i;
if (cur + val * i - i - cache <= 6000) {
cache += i;
cnt[tot]++;
val = val * i;
dfs(cur + 1, i);
val = val / i;
cnt[tot]--;
cache -= i;
}
tot--;
}
}
int main () {
dfs(0, 1);
scanf("%d", &t);
while (t--) {
scanf("%d", &n);
printf("%lld\n", f[n]);
}
return 0;
}
J. Stone game
#include
#include
#include
using namespace std;
typedef long long ll;
const int N = 301;
const int M = 80000;
const int mod = 1e9 + 7;
int t, p[N], n, m, m0, m1;
ll cnt[M];
int main () {
scanf("%d", &t);
while (t--) {
scanf("%d", &n);
m = 0;
for (int i = 0; i < n; i++) {
scanf("%d", &p[i]);
p[i] = -p[i];
m -= p[i];
}
sort(p, p + n);
m0 = m / 2;
m1 = m - m0;
ll ans = 0;
memset(cnt, 0, sizeof(cnt));
cnt[0] = 1;
for (int i = 0; i < n; i++) {
p[i] = -p[i];
for (int j = m0; j >= 0; j--) {
if (cnt[j] == 0) continue;
if (j + p[i] >= m1 && j <= m - j - p[i]) {
ans = (ans + cnt[j]) % mod;
}
if (j + p[i] <= m0) {
cnt[j + p[i]] = (cnt[j + p[i]] + cnt[j]) % mod;
}
}
}
printf("%lld\n", ans);
}
}
L. Digit sum
#include
using namespace std;
const int N = 1e6 + 10;
const int B = 10 + 10;
int t, a, b;
int f[N][B];
int val[30];
void init () {
int n, b, cnt;
for (b = 2; b <= 10; b++) {
cnt = 0;
for (int i = 0; i < 30; i++) val[i] = 0;
for (n = 1; n <= 1e6; n++) {
// printf("%d %d\n", n, b);
for (int i = 0; i < 30; i++) {
val[i]++;
cnt++;
if (val[i] < b) break;
val[i] = 0;
cnt -= b;
}
f[n][b] += cnt + f[n-1][b];
}
}
}
int main () {
init();
scanf("%d", &t);
for (int kase = 1; kase <= t; kase++) {
int ans = 0;
scanf("%d%d", &a, &b);
printf("Case #%d: %d\n", kase, f[a][b]);
}
return 0;
}