具体集训
xujunlang2011 · · 个人记录
9.22-23
T1(set)
给定正整数
发现
时间
#include<bits/stdc++.h>
using namespace std;
const long long N = 305, p = 998244353;
long long T, n, t[N * N], ans = 1;
long long _pow(long long a, long long b)
{
long long sum = 1;
while (b)
{
if (b & 1)
{
sum *= a;
sum %= p;
}
a *= a;
a %= p;
b >>= 1;
}
return sum;
}
int main()
{
freopen("set.in", "r", stdin);
freopen("set.out", "w", stdout);
cin >> n;
for (int i = 1;i <= n;i++)
{
for (int j = i * (i + 1) / 2;j >= 1;j--)
{
t[j + i] += t[j];
t[j + i] %= p - 1;
}
t[i]++;
t[i] %= p - 1;
}
for (int i = 1;i <= n * (n + 1) / 2;i++)
{
ans *= _pow(i, t[i]);
ans %= p;
}
cout << ans;
return 0;
}
T2(hire)
富萝莉白浅有
现在有 YES 或 NO 表示目前白浅能否给每个人都分配到理想的房间。
赛时写了个暴力贪心拿了
若
将
然后找到小白逛公园。
代码被次掉了。
T3(block)
给定一棵根为 1 的包含 dfs 序为 dfs 序不相邻。请在这棵树上找到满足题目限制条件的权值之和最大的连通块。
备注 1:
一个结点可能有多个孩子结点,这些孩子是有 dfs 的先后顺序的,dfs 顺序就是题目输入
的顺序。
备注 2:
连通块的 dfs 序的定义:找到连通块在原树上深度最小的点开始 dfs,然后仍然根据题目
读入的顺序获取每个点的 dfs 顺序。
不会。
T4(checkers)
白浅妹妹喜欢玩跳棋,她定义唯一合法的跳法是一个棋子
先考虑没有 ? 的情况。
可以发现 11 可以自由移动。
还发现 11 在 1 的左边还是右边对方案数没影响,所以可以将单独的 1 删除。
现在只剩了 0 和 11,11 可以插入两个 0 或者 11 之间,设有 0,11,答案就是
每日任务:费马小定理(2/1)
再考虑有问号的。
设 0 和 11 的方案数,1 能不能凑出一个 11。
然后发现
这时我们可以用类似弗洛伊德(
转移自己推到代码里看。
然后没了。
#include<bits/stdc++.h>
using namespace std;
const long long p = 1e9 + 7;
long long T, n, j[1000], dp[2][1000][1000][2], ans;
string s;
long long _pow(long long a, long long b)
{
long long sum = 1;
while (b)
{
if (b & 1)
{
sum *= a;
sum %= p;
}
a *= a;
a %= p;
b >>= 1;
}
return sum;
}
long long check(int a, int b)
{
return j[b] * _pow(j[a] * j[b - a] % p, p - 2) % p;
}
int main()
{
freopen("checkers.in", "r", stdin);
freopen("checkers.out", "w", stdout);
cin >> n >> s;
s = " " + s + " ";
j[0] = dp[0][0][0][0] = 1;
for (int i = 1;i <= n;i++)
{
j[i] = j[i - 1] * i % p;
}
for (int i = 1;i <= n;i++)
{
for (int j = 0;j <= n;j++)
{
for (int k = 0;k <= n;k++)
{
dp[i % 2][j][k][0] = dp[i % 2][j][k][1] = 0;
if (s[i] != '0')
{
if (j)
{
dp[i % 2][j][k][0] += dp[i % 2 ^ 1][j - 1][k][1];
}
dp[i % 2][j][k][1] += dp[i % 2 ^ 1][j][k][0];
}
if (s[i] != '1')
{
if (k)
{
dp[i % 2][j][k][0] += dp[i % 2 ^ 1][j][k - 1][0] + dp[i % 2 ^ 1][j][k - 1][1];
}
}
dp[i % 2][j][k][0] %= p;
dp[i % 2][j][k][1] %= p;
}
}
}
for (int i = 0;i <= n;i++)
{
for (int j = 0;j <= n;j++)
{
ans += (dp[n % 2][i][j][0] + dp[n % 2][i][j][1]) % p * check(i, i + j) % p;
ans %= p;
}
}
cout << ans;
return 0;
}
9.24
臭题目(悲)
T1(yiyi)
从前有个寺庙,名为依依寺。寺庙因《诗经·小雅》中的“昔我往矣,杨柳依依。今我来思,雨雪霏霏。” 而得名。
庙里有个老和尚和小和尚。老和尚叫章丘样,小和尚叫章吊痒。老和尚说“从前有个寺庙,名为依依寺。庙里有个老和尚和小和尚。老和尚叫章丘样,小和尚叫章吊痒......”
有一天,老和尚在拨算盘。他脑海中蹦出了这么一道题:
有
由于
输入格式
第一行,输入数据组数
接下来
输出格式
输出共 First,否则输出 Second。
赛时没发现两个人数共用磕了三小时没过样例喜爆零。
赛后被大粪讨恶心。
直接给代码。
#include<bits/stdc++.h>
using namespace std;
int main()
{
freopen("yiyi.in", "r", stdin);
freopen("yiyi.out", "w", stdout);
int T;
cin >> T;
for (int i = 1;i <= T;i++)
{
long long a, b, c;
cin >> a >> b >> c;
if (a % 2 == 1 && (b == 0 && c <= 1 || b - 1 <= c && c <= b + 1) || a % 2 == 0 && (b == 0 && c != 1 || b > 1 && c == 0))
{
cout << "Second\n";
}
else
{
cout << "First\n";
}
}
return 0;
}
T2(wuyi)
从前有个寺庙,名为武义寺。庙里有个老和尚和小和尚。老和尚叫扶弱给,小和尚叫扶弱呱。老和尚说 “从前有个寺庙,名为武义寺。庙里有个老和尚和小和尚。老和尚叫扶弱给,小和尚叫扶弱呱......”
有一天,扶弱给在潜心研究排列。他在脑中随机一个排列的时候,脑海里冒出了这样一个问题:
对于一个排列
可是
输入格式
一行一个正整数
输出格式
输出
赛时推柿子推错了喜爆零。
还是分讨,对每一位计算
#include<bits/stdc++.h>
using namespace std;
const long long p = 998244353;
long long n, j = 1, ans;
long long _pow(long long a, long long b)
{
long long sum = 1;
while (b)
{
if (b & 1)
{
sum *= a;
sum %= p;
}
a *= a;
a %= p;
b >>= 1;
}
return sum;
}
int main()
{
freopen("wuyi.in", "r", stdin);
freopen("wuyi.out", "w", stdout);
cin >> n;
ans = n + 1;
for (int i = 1;i <= n;i++)
{
j *= i;
j %= p;
ans += (n + 1 - i) * j % p * ((_pow(i + 1, n - i) - _pow(i, n - i)) % p + p) % p;
ans %= p;
}
cout << ans * _pow(j, p - 2) % p;
return 0;
}
T3(yijiu)
传说中,小喵和小矣是一对夫妻,他们关系很和洽。由于两位都是数学系毕业的,所以平日里他们经常一起研究数学。
最近,他们发现,一个数不仅可以被若干个不同的二进制分解,还可以被若干个斐波那契数分解!
这里定义
形式化地。设
小喵定义
例如
小矣紧接着想知道,如果给定
由于小矣脑子里有许多疑惑,所以他会询问你很多次。
输入格式
第一行,输入查询组数
接下来
输出格式
输出共
设
首先二分找到第一个小于等于
易得
然后记搜。
#include<bits/stdc++.h>
using namespace std;
long long T, l, r, f[100], n = 87;
map <long long, long long> dp;
long long S(long long k)
{
if (k == 0)
{
return k;
}
if (dp[k])
{
return dp[k];
}
int l = 1, r = n, mid;
while (l < r)
{
mid = (l + r + 1) / 2;
if (f[mid] <= k)
{
l = mid;
}
else
{
r = mid - 1;
}
}
return dp[k] = (S(f[l] - 1) ^ S(k - f[l]) ^ (k % 2 == f[l] % 2 ? f[l] : 0));
}
int main()
{
freopen("yijiu.in", "r", stdin);
freopen("yijiu.out", "w", stdout);
f[0] = f[1] = 1;
for (int i = 2;i <= n;i++)
{
f[i] = f[i - 1] + f[i - 2];
}
cin >> T;
for (int ti = 1;ti <= T;ti++)
{
cin >> l >> r;
cout << (S(r) ^ S(l - 1)) << "\n";
}
return 0;
}
T4(pear)
传说中,早在公元前
补幺人通过“补幺梨”货币来进行交易。具体地,“补幺梨”有 n 种面值,分别为
补幺人认为,在他们的视野里,
补幺国王掌管大权,每种补幺梨他都有
古人的智商自然是有限的,因此他们只能意识到问题,但不能解决问题。
作为十万年后的我们,古人借助时光机向我们发出求助。你需要帮他们计算出最大的不能被表示的面额。
输入格式
第一行,输入两个数
第二行,输入
保证
输出格式
你需要帮补幺人计算出最大不能被表示的面额。
不难发现,在给定的数据范围下,必定存在不能被表示的面额。
听说是个背包,不会。
9.25
扑克(poker)
全体起立!
鸡尾酒和智乃在玩一个扑克牌游戏。
游戏规则是这样的:
从一幅扑克牌(不含大小王,共
手牌有以下几种种类(按照优先级从大到小排序):
其中,顺子不能向上越过
如果两人的牌型是一致的,那么,按照关键牌组从大到小去比较,例如两人分别是:
则第一个人胜,因为一对
在这个游戏中,
对于同点数,不同花色的牌,在游戏中视作一样大小的牌,但在输出中,黑桃
如果你想更具体的阅读比较大小的规则,可以看题目最下方的解释。
鸡尾酒为了赢这个游戏,买了一副透视眼镜,可以看到智乃的底牌。 为了羞辱智乃,鸡尾酒决定,每次都想象出两张刚刚好可以稳赢智乃的牌,请帮助鸡尾酒计算,想象出的那两张牌分别应该是什么,或者告诉鸡尾酒,他无法获胜。
伟大,无需多言。
#include<bits/stdc++.h>
using namespace std;
int T, c[128], f;
char d[20], e[5];
struct node
{
char a, b;
}p1[6], p2[6], pp1[6], pp2[6], ppp1[6];
bool cmp (node a, node b)
{
return c[a.b] > c[b.b] || (c[a.b] == c[b.b] && c[a.a] < c[b.a]);
}
bool cmp_out (node a, node b)
{
return c[a.b] < c[b.b] || (c[a.b] == c[b.b] && c[a.a] < c[b.a]);
}
bool check1 (int g)
{
if (g == 1)
{
if (p1[1].a == p1[2].a && p1[2].a == p1[3].a && (c[p1[1].b] > c[p2[1].b] || f != g))
{
if (c[p1[3].b] - c[p1[1].b] <= 4)
{
int u = min(c[p1[1].b] + 4, 14);
if (u > c[p2[5].b] || f != g)
{
u = min(u, max(c[p2[5].b] + 1, c[p1[3].b]));
if (f != g)
{
u = max(c[p1[3].b], 6);
}
p1[4].a = p1[5].a = p1[1].a;
for (int i = u - 4;i <= u;i++)
{
p1[i - u + 5].b = d[i];
}
return 0;
}
}
}
}
if (g == 2)
{
if (p1[1].b == p1[2].b && p1[2].b == p1[3].b)
{
if (c[p1[1].b] > c[p2[1].b] || f != g)
{
p1[4].b = p1[1].b;
for (int i = 1;i <= 4;i++)
{
p1[i].a = e[i];
}
p1[5].a = e[4];
if (p1[1].b == '2')
{
p1[5].b = '3';
}
else
{
p1[5].b = '2';
}
return 0;
}
else if (p1[1].b == p2[1].b && p2[5].b != 'A')
{
p1[4].b = p1[1].b;
for (int i = 1;i <= 4;i++)
{
p1[i].a = e[i];
}
p1[5].a = e[4];
p1[5].b = d[c[p2[5].b] + 1];
return 0;
}
}
else if (p1[1].b == p1[2].b || p1[2].b == p1[3].b)
{
char u;
if (p1[1].b != p1[2].b)
{
p1[5].a = p1[1].a;
p1[5].b = p1[1].b;
u = p1[2].b;
}
else
{
p1[5].a = p1[3].a;
p1[5].b = p1[3].b;
u = p1[1].b;
}
if (c[u] > c[p2[1].b] || c[u] == c[p2[1].b] && c[p1[5].b] > c[p2[5].b] || f != g)
{
for (int i = 1;i <= 4;i++)
{
p1[i].a = e[i];
p1[i].b = u;
}
return 0;
}
}
}
if (g == 3)
{
if (p1[1].b == p1[2].b && p1[2].b == p1[3].b)
{
for (int i = 4;i <= 5;i++)
{
p1[i].a = e[i - 1];
}
if (p1[1].b == '2')
{
for (int i = 4;i <= 5;i++)
{
p1[i].b = '3';
}
}
else
{
for (int i = 4;i <= 5;i++)
{
p1[i].b = '2';
}
}
return 0;
}
else if (p1[1].b == p1[2].b || p1[2].b == p1[3].b)
{
if (p1[1].b != p1[2].b)
{
for (int i = 4;i <= 5;i++)
{
p1[i].b = p1[1].b;
}
if (p1[1].a == e[1])
{
for (int i = 4;i <= 5;i++)
{
p1[i].a = e[i - 1];
}
}
else
{
p1[1].a = e[2];
for (int i = 4;i <= 5;i++)
{
p1[i].a = e[i - 1];
}
}
}
else
{
for (int i = 4;i <= 5;i++)
{
p1[i].b = p1[i - 2].b;
}
if (p1[1].a != e[4] && p1[2].a != e[4])
{
p1[4].a = e[4];
}
else if (p1[1].a != e[3] && p1[2].a != e[3])
{
p1[4].a = e[3];
}
else
{
p1[4].a = e[2];
}
if (p1[3].a != e[4])
{
p1[5].a = e[4];
}
else
{
p1[5].a = e[3];
}
}
return 0;
}
}
if (g == 4)
{
if (p1[1].a == p1[2].a && p1[2].a == p1[3].a)
{
if (f != g)
{
int t[15], u = 2, uu = 0;
if (c[p1[3].b] - c[p1[1].b] <= 4 && c[p1[3].b] <= 6)
{
uu = 1;
}
if (c[p1[1].b] == 4 && c[p1[3].b] == 6)
{
uu = 2;
}
for (int i = 2;i <= 14;i++)
{
t[i] = 0;
}
t[c[p1[1].b]] = t[c[p1[2].b]] = t[c[p1[3].b]] = 1;
p1[4].a = p1[5].a = p1[1].a;
for (int i = 2;i <= 14;i++)
{
if (!t[i])
{
t[i] = 2;
u--;
}
if (!u)
{
break;
}
}
if (uu == 1)
{
for (int i = min(c[p1[1].b] + 4, 14);i >= c[p1[1].b];i--)
{
if (t[i] == 2 && uu)
{
t[i] = 0;
for (int j = i + 1;j <= 14;j++)
{
if (!t[j])
{
t[j] = 1;
break;
}
}
break;
}
}
}
else if (uu == 2)
{
for (int i = c[p1[1].b] + 1;i >= 2;i--)
{
if (t[i] == 2 && uu)
{
t[i] = 0;
for (int j = i + 1;j <= 14;j++)
{
if (!t[j])
{
t[j] = 1;
break;
}
}
break;
}
}
}
u = 1;
for (int i = 2;i <= 14;i++)
{
if (t[i])
{
p1[u++].b = d[i];
}
}
return 0;
}
else
{
p1[4].a = p1[5].a = p1[1].a;
int t[15];
for (int i = 2;i <= 14;i++)
{
t[i] = 0;
}
t[c[p1[1].b]] = t[c[p1[2].b]] = t[c[p1[3].b]] = 1;
for (int i = 3;i <= 14;i++)
{
if (!t[i])
{
for (int j = 2;j < i;j++)
{
if (!t[j])
{
p1[4].b = d[i];
p1[5].b = d[j];
sort(p1 + 1, p1 + 6, cmp);
if (c[p1[1].b] - c[p1[5].b] > 4)
{
for (int l = 1;l <= 5;l++)
{
if (c[p1[l].b] > c[p2[l].b])
{
return 0;
}
if (c[p2[l].b] > c[p1[l].b])
{
break;
}
}
}
for (int l = 1;l <= 3;l++)
{
p1[l].a = pp1[l].a;
p1[l].b = pp1[l].b;
}
}
}
}
}
return 1;
}
}
}
if (g == 5)
{
if (c[p1[3].b] - c[p1[1].b] <= 4 && p1[1].b != p1[2].b && p1[2].b != p1[3].b)
{
if (p2[1].b == 'A' && f == g)
{
return 1;
}
int u = min(c[p1[1].b] + 4, 14);
if (u > c[p2[1].b] || f != g)
{
u = min(u, max(c[p2[1].b] + 1, c[p1[3].b]));
if (f != g)
{
u = max(c[p1[3].b], 6);
}
if (c[p1[1].b] >= u - 4 || f != g)
{
p1[4].a = p1[5].a = e[4];
if (p1[1].a == p1[2].a && p1[2].a == p1[3].a && p1[3].a == e[4])
{
p1[4].a = e[3];
}
int t[15], uu = 4;
for (int i = 2;i <= 14;i++)
{
t[i] = 0;
}
t[c[p1[1].b]] = t[c[p1[2].b]] = t[c[p1[3].b]] = 1;
for (int i = u - 4;i <= u;i++)
{
if (!t[i])
{
p1[uu].b = d[i];
uu++;
}
}
return 0;
}
}
}
}
if (g == 6)
{
if (p1[1].b != p1[2].b && p1[2].b != p1[3].b)
{
if (c[p1[1].b] > c[p2[3].b] || c[p1[1].b] == c[p2[3].b] && c[p1[3].b] > c[p2[4].b] || c[p1[1].b] == c[p2[3].b] && c[p1[3].b] == c[p2[4].b] && c[p1[2].b] > c[p2[5].b])
{
p1[4].b = p1[5].b = p1[1].b;
if (p1[1].a == e[1])
{
for (int i = 4;i <= 5;i++)
{
p1[i].a = e[i - 1];
}
}
else
{
p1[1].a = e[2];
for (int i = 4;i <= 5;i++)
{
p1[i].a = e[i - 1];
}
}
return 0;
}
if (c[p1[2].b] > c[p2[3].b] || c[p1[2].b] == c[p2[3].b] && c[p1[3].b] > c[p2[4].b] || c[p1[2].b] == c[p2[3].b] && c[p1[3].b] == c[p2[4].b] && c[p1[1].b] > c[p2[5].b])
{
p1[4].b = p1[5].b = p1[2].b;
if (p1[2].a == e[1])
{
for (int i = 4;i <= 5;i++)
{
p1[i].a = e[i - 1];
}
}
else
{
p1[2].a = e[2];
for (int i = 4;i <= 5;i++)
{
p1[i].a = e[i - 1];
}
}
return 0;
}
if (c[p1[3].b] > c[p2[3].b] || c[p1[3].b] == c[p2[3].b] && c[p1[2].b] > c[p2[4].b] || c[p1[3].b] == c[p2[3].b] && c[p1[2].b] == c[p2[4].b] && c[p1[1].b] > c[p2[5].b])
{
p1[4].b = p1[5].b = p1[3].b;
if (p1[3].a == e[1])
{
for (int i = 4;i <= 5;i++)
{
p1[i].a = e[i - 1];
}
}
else
{
p1[3].a = e[2];
for (int i = 3;i <= 5;i++)
{
p1[i].a = e[i - 1];
}
}
return 0;
}
}
else if (p1[1].b == p1[2].b && p1[2].b == p1[3].b)
{
if (c[p1[1].b] > c[p2[1].b])
{
p1[4].a = p1[5].a = e[4];
for (int i = 4;i <= 5;i++)
{
p1[i].b = d[i - 2];
}
return 0;
}
else if (c[p1[1].b] == c[p2[1].b])
{
int t[15];
for (int i = 2;i <= 14;i++)
{
t[i] = 0;
}
t[c[p1[1].b]] = t[c[p1[2].b]] = t[c[p1[3].b]] = 1;
for (int i = 3;i <= 14;i++)
{
if (!t[i])
{
for (int j = 2;j < i;j++)
{
if (!t[j])
{
p1[4].b = d[i];
p1[5].b = d[j];
sort(p1 + 4, p1 + 6, cmp);
for (int l = 1;l <= 5;l++)
{
if (c[p1[l].b] > c[p2[l].b])
{
p1[4].a = p1[5].a = e[4];
return 0;
}
if (c[p2[l].b] > c[p1[l].b])
{
break;
}
}
for (int l = 1;l <= 3;l++)
{
p1[l].b = pp1[l].b;
}
}
}
}
}
}
}
else
{
p1[4].b = pp1[4].b = p1[2].b;
if (p1[1].b == p1[2].b)
{
if (p1[1].a != e[4] && p1[2].a != e[4])
{
p1[4].a = pp1[4].a = e[4];
}
else if (p1[1].a != e[3] && p1[2].a != e[3])
{
p1[4].a = pp1[4].a = e[3];
}
else
{
p1[4].a = pp1[4].a = e[2];
}
sort(p1 + 1, p1 + 5, cmp_out);
sort(pp1 + 1, pp1 + 5, cmp_out);
}
else
{
if (p1[2].a != e[4] && p1[3].a != e[4])
{
p1[4].a = pp1[4].a = e[4];
}
else if (p1[2].a != e[3] && p1[3].a != e[3])
{
p1[4].a = pp1[4].a = e[3];
}
else
{
p1[4].a = pp1[4].a = e[2];
}
sort(p1 + 1, p1 + 5, cmp);
sort(pp1 + 1, pp1 + 5, cmp);
}
for (int i = 2;i <= 14;i++)
{
if (i != c[p1[1].b] && i != c[p1[4].b])
{
p1[5].b = d[i];
p1[5].a = e[4];
sort(p1 + 4, p1 + 6, cmp);
for (int l = 1;l <= 5;l++)
{
if (c[p1[l].b] > c[p2[l].b])
{
return 0;
}
if (c[p2[l].b] > c[p1[l].b])
{
break;
}
}
p1[4].a = pp1[4].a;
p1[4].b = pp1[4].b;
}
}
}
}
return 1;
}
bool check2 (int g)
{
if (g == 1)
{
if (p2[1].a == p2[2].a && p2[2].a == p2[3].a)
{
if (c[p2[3].b] - c[p2[1].b] <= 4)
{
int u = min(c[p2[1].b] + 4, 14);
p2[4].a = p2[5].a = p2[1].a;
for (int i = u - 4;i <= u;i++)
{
p2[i - u + 5].b = d[i];
}
return 0;
}
}
}
if (g == 2)
{
if (p2[1].b == p2[2].b && p2[2].b == p2[3].b)
{
p2[4].b = p2[1].b;
for (int i = 1;i <= 4;i++)
{
p2[i].a = e[i];
}
p2[5].a = e[1];
if (p2[1].b == 'A')
{
p2[5].b = 'K';
}
else
{
p2[5].b = 'A';
}
return 0;
}
else if (p2[1].b == p2[2].b || p2[2].b == p2[3].b)
{
char u;
if (p2[1].b != p2[2].b)
{
p2[5].a = p2[1].a;
p2[5].b = p2[1].b;
u = p2[2].b;
}
else
{
p2[5].a = p2[3].a;
p2[5].b = p2[3].b;
u = p2[1].b;
}
for (int i = 1;i <= 4;i++)
{
p2[i].a = e[i];
p2[i].b = u;
}
return 0;
}
}
if (g == 3)
{
if (p2[1].a == p2[2].a && p2[2].a == p2[3].a)
{
int t[15], u = 2;
for (int i = 2;i <= 14;i++)
{
t[i] = 0;
}
t[c[p2[1].b]] = t[c[p2[2].b]] = t[c[p2[3].b]] = 1;
p2[4].a = p2[5].a = p2[1].a;
for (int i = 14;i >= 2;i--)
{
if (!t[i])
{
p2[u + 3].b = d[i];
u--;
}
if (!u)
{
break;
}
}
sort(p2 + 1, p2 + 6, cmp);
return 0;
}
}
if (g == 4)
{
if (c[p2[3].b] - c[p2[1].b] <= 4)
{
int t[15], uu = 0, u = min(int(c[p2[1].b] + 4), 14);
for (int i = u - 4;i <= u;i++)
{
t[i] = 0;
}
p2[4].a = p2[5].a = e[1];
t[c[p2[1].b]] = t[c[p2[2].b]] = t[c[p2[3].b]] = 1;
for (int i = u;i >= u - 4;i--)
{
if (!t[i])
{
uu++;
p2[uu + 3].b = d[i];
}
}
sort(p2 + 1, p2 + 6, cmp);
return 0;
}
}
if (g == 5)
{
p2[4].b = p2[5].b = p2[3].b;
if (p2[3].a == 'D')
{
for (int i = 4;i <= 5;i++)
{
p2[i].a = e[i - 3];
}
}
else
{
for (int i = 3;i <= 5;i++)
{
p2[i].a = e[i - 2];
}
}
sort(p2 + 1, p2 + 6, cmp);
return 0;
}
return 1;
}
int main()
{
freopen("poker.in", "r", stdin);
freopen("poker.out", "w", stdout);
for (int i = 2;i <= 9;i++)
{
c[i + '0'] = i;
d[i] = i + '0';
}
c[int('T')] = 10;
c[int('J')] = 11;
c[int('Q')] = 12;
c[int('K')] = 13;
c[int('A')] = 14;
d[10] = 'T';
d[11] = 'J';
d[12] = 'Q';
d[13] = 'K';
d[14] = 'A';
c[int('S')] = 1;
c[int('H')] = 2;
c[int('C')] = 3;
c[int('D')] = 4;
e[1] = 'S';
e[2] = 'H';
e[3] = 'C';
e[4] = 'D';
cin >> T;
for (int ti = 1;ti <= T;ti++)
{
for (int i = 1;i <= 3;i++)
{
cin >> p1[i].a >> p1[i].b;
ppp1[i].a = pp1[i].a = p1[i].a;
ppp1[i].b = pp1[i].b = p1[i].b;
}
for (int i = 1;i <= 3;i++)
{
cin >> p2[i].a >> p2[i].b;
pp2[i].a = p2[i].a;
pp2[i].b = p2[i].b;
}
int l = 1;
while (check2(l))
{
l++;
}
if (l >= 3)
{
l++;
}
f = l;
while (check1(l) && l > 0)
{
l--;
for (int i = 1;i <= 3;i++)
{
pp1[i].a = ppp1[i].a;
pp1[i].b = ppp1[i].b;
p1[i].a = pp1[i].a;
p1[i].b = pp1[i].b;
}
}
if (l == 0)
{
cout << -1 << "\n";
}
else
{
sort(p1 + 1, p1 + 6, cmp_out);
for (int i = 1;i <= 5;i++)
{
cout << p1[i].a << p1[i].b << " ";
}
cout << "\n";
}
}
return 0;
}
其实这是 T4。
你猜右侧快速跳转是做什么的(
,我们则称这个点
数组中第一个元素和最后一个元素永远不可能为山谷点。
一个数组的价值是所有山谷点之和。
至多修改
设
转移要注意本来是不是山谷。
然后秒了。
#include<bits/stdc++.h>
using namespace std;
const int N = 2e3 + 5;
long long n, k, a[N], dp[N][N][2], ans = -1;
int main()
{
freopen("change.in", "r", stdin);
freopen("change.out", "w", stdout);
cin >> n >> k;
for (int i = 1;i <= n;i++)
{
cin >> a[i];
}
for (int i = 2;i < n;i++)
{
for (int j = 0;j <= k;j++)
{
if (a[i - 1] > a[i] && a[i] < a[i + 1])
{
dp[i][j][0] = dp[i - 1][j][1];
dp[i][j][1] = dp[i - 1][j][0] + a[i];
}
else
{
dp[i][j][0] = max(dp[i - 1][j][0], dp[i - 1][j][1]);
if (j != 0)
{
dp[i][j][1] = dp[i - 1][j - 1][0] + min(a[i - 1], a[i + 1]) - 1;
}
}
ans = max(ans, max(dp[i][j][0], dp[i][j][1]));
}
}
cout << ans;
return 0;
}
10.9
T1(exchange)
有一个
数据只有 sort秒了。
#include<bits/stdc++.h>
using namespace std;
int t, n, m, f;
struct node
{
int w[105];
}h[105];
bool cmp(node a, node b)
{
for (int i = 1;i <= m;i++)
{
if (a.w[i] != b.w[i])
{
return a.w[i] < b.w[i];
}
}
return 1;
}
int main()
{
freopen("exchange.in", "r", stdin);
freopen("exchange.out", "w", stdout);
cin >> t;
for (int ti = 1;ti <= t;ti++)
{
cin >> n >> m;
for (int i = 1;i <= n;i++)
{
for (int j = 1;j <= m;j++)
{
cin >> h[i].w[j];
}
}
sort(h + 1, h + n + 1, cmp);
f = 1;
for (int i = 1;i <= m;i++)
{
for (int j = 1;j < n;j++)
{
if (h[j].w[i] > h[j + 1].w[i])
{
f = 0;
break;
}
}
if (!f)
{
break;
}
}
if (f)
{
cout << "YES\n";
}
else
{
cout << "NO\n";
}
}
return 0;
}
T2(brick)
有一个
除了最后一层的砖块外,每一个砖块都和下面一层的两个砖块相邻,呈现这样的形状:
塔上面只有红黄蓝三种颜色的砖块,并且有以下规律:
-
若相邻的两块砖块是相同颜色,那么这两块方砖紧挨的上面的砖块也将会是相同的颜色
-
若相邻的两块砖块是不同颜色,那么这两块方砖紧挨的上面的砖块将会是没有出现的第三种颜色
现在告诉你最下面一层的 A B C 表示),需要你推出塔顶部的颜色。
一个不容易发现的性质,设:
红
黄
#include<bits/stdc++.h>
using namespace std;
int t, n, f[128], ans;
char g[3];
string s;
int c(int x, long long y)
{
if (x == 0)
{
return 1;
}
if (x == 1)
{
return y % 3;
}
if (x == 2)
{
return y * (y - 1) / 2 % 3;
}
return c(x / 3, y / 3) * c(x % 3, y % 3) % 3;
}
int main()
{
freopen("brick.in", "r", stdin);
freopen("brick.out", "w", stdout);
f['A'] = 0, g[0] = 'A';
f['B'] = 1, g[1] = 'B';
f['C'] = 2, g[2] = 'C';
cin >> t;
for (int ti = 1;ti <= t;ti++)
{
cin >> n >> s;
for (int i = 0;i < n;i++)
{
ans += f[int(s[i])] * c(i, n - 1) % 3;
ans %= 3;
}
cout << g[(ans * (n % 2 * 2 - 1) + 3) % 3] << "\n";
ans = 0;
}
return 0;
}
蓝
于是可以用杨辉三角推出塔尖。
10.10
T1(collect)
Dr.Wang 是一位植物领域的专家。他要给他的学生们上一节课。课堂上需要展示一种植物。众所周知,植物的生长是有阶段的,本着严谨科学的态度,Dr.Wang 希望可以在课堂上给学生们展示该植物的每个生长阶段。
上图为植物“向日葵”的七个生长阶段。
Dr.Wang 要讲授的植物有
-
以
a_i 的价格购买一株生长到第i 个阶段的植物。 -
花费
k 的代价使用催熟科技,将所有已购买的植物生长阶段增加1 。若一株植物已经到了阶段n ,则返回阶段1 。(可以理解为成熟到只剩种子,然后被重新种下去了)
现在 Dr.Wang 想让你帮忙求出,他最少需要花费多少代价,可以收集到植物的每个生长阶段。
设 ∗替换之后匹配了目标文件前
若
还有一个操作,
#include<bits/stdc++.h>
using namespace std;
const int N = 5e4 + 5, p = 998244853;
long long n, m, dp[N][1005], sum[N][1005], l, ans;
string s, t[N];
int main()
{
freopen("char.in", "r", stdin);
freopen("char.out", "w", stdout);
cin >> n >> m >> s;
s = " " + s;
for (int i = 1;i <= m;i++)
{
cin >> t[i];
t[i] = " " + t[i];
}
for (int k = 1;k <= m;k++)
{
l = t[k].size() - 1;
for (int i = 0;i <= n;i++)
{
for (int j = 0;j <= l;j++)
{
dp[i][j] = sum[i][j] = 0;
}
}
for (int i = 1;i <= n;i++)
{
if (s[i] == '*')
{
dp[i][0] = dp[i - 1][0] + 1;
for (int j = 1;j <= l;j++)
{
dp[i][j] = (sum[i - 1][j] + dp[i - 1][0] + 1) % p;
sum[i][j] = (sum[i][j - 1] + dp[i][j]) % p;
}
}
else
{
for (int j = 1;j <= l;j++)
{
if (s[i] == t[k][j])
{
dp[i][j] = dp[i - 1][j - 1];
if (j == 1)
{
dp[i][j]++;
}
}
sum[i][j] = (sum[i][j - 1] + dp[i][j]) % p;
}
}
ans += dp[i][l];
ans %= p;
}
}
cout << ans;
return 0;
}
T2(tree)
一棵
设
抽象数学题。
省流:
我们定义
接下来手算比较小的几个。
注:以下的
所以总结一下
于是我们愉快地……T了。
继续优化,将
画个图看看:
我们可以将它分为
第一个部分:
很显然是
第二个部分:
很显然是
第三个部分:
很显然是
所以
再考虑奇数:
再画一个图:
我们也可以将它分为
第一个部分:
其实这是刚才的图
很显然是
第二个部分:
很显然是
第三个部分:
很显然也是
所以
把奇数和偶数的式子合并得到:
最后的最后,用总方案数减去
#include<bits/stdc++.h>
using namespace std;
const int p = 1e9 + 7;
long long n, m;
long long _pow(long long a, long long b)
{
long long sum = 1;
while (b)
{
if (b & 1)
{
sum *= a;
sum %= p;
}
a *= a;
a %= p;
b >>= 1;
}
return sum;
}
long long sum(long long k)
{
k %= p;
return k * (k + 1) % p * _pow(2, p - 2) % p;
}
long long sum2(long long k)
{
k %= p;
return k * (k + 1) % p * (k * 2 + 1) % p * _pow(6, p - 2) % p;
}
int main()
{
freopen("wooden.in", "r", stdin);
freopen("wooden.out", "w", stdout);
cin >> n;
m = (n * 3 - 2) % p;
cout << (m * (m + 1) % p * (m + 2) % p * _pow(6, p - 2) % p - (sum2(n / 2) + sum2((n - 1) / 2) + sum((n - 1) / 2)) % p + p * 2) % p;
return 0;
}
程序员节
悻猩场。
T1
给定
最后开的题,主要是长得太抽象了。
笑点解析:
不难发现,多个长方体组成的体积交长方体由最右边的左面(4声),最上边的下面……组成。
所以可以维护每个维度的前后缀最值算出
然后考虑容斥,发现任意两个体积交的交为所有长方体的体积交,所以算出答案之后减去
#include<bits/stdc++.h>
using namespace std;
const int N = 1e5 + 5, inf = 1e9;
long long n, a[4][N][3], b[4][N][3], num, ans;
int main()
{
freopen("cube.in", "r", stdin);
freopen("cube.out", "w", stdout);
cin >> n;
for (int i = 1;i <= n;i++)
{
cin >> a[1][i][0] >> a[2][i][0] >> a[3][i][0] >> b[1][i][0] >> b[2][i][0] >> b[3][i][0];
}
for (int i = 1;i <= 3;i++)
{
a[i][0][1] = -inf;
b[i][0][1] = inf;
a[i][n + 1][2] = -inf;
b[i][n + 1][2] = inf;
for (int j = 1;j <= n;j++)
{
a[i][j][1] = max(a[i][j - 1][1], a[i][j][0]);
b[i][j][1] = min(b[i][j - 1][1], b[i][j][0]);
}
for (int j = n;j >= 1;j--)
{
a[i][j][2] = max(a[i][j + 1][2], a[i][j][0]);
b[i][j][2] = min(b[i][j + 1][2], b[i][j][0]);
}
}
num = (b[1][n][1] - a[1][n][1] + 1) * (b[2][n][1] - a[2][n][1] + 1) * (b[3][n][1] - a[3][n][1] + 1);
for (int i = 1;i <= n;i++)
{
ans += (min(b[1][i - 1][1], b[1][i + 1][2]) - max(a[1][i - 1][1], a[1][i + 1][2]) + 1) * (min(b[2][i - 1][1], b[2][i + 1][2]) - max(a[2][i - 1][1], a[2][i + 1][2]) + 1) * (min(b[3][i - 1][1], b[3][i + 1][2]) - max(a[3][i - 1][1], a[3][i + 1][2]) + 1) - num;
}
cout << ans + num;
return 0;
}
T2
给定一个长为
很像数据结构的诈骗题。
可以发现假如出题人想卡你,数列就为斐波那契数列,不超过 Yes。
#include<bits/stdc++.h>
using namespace std;
const int N = 1e5 + 5;
long long n, q, a[N], b[N], x, y;
int main()
{
freopen("triangle.in", "r", stdin);
freopen("triangle.out", "w", stdout);
cin >> n >> q;
for (int i = 1;i <= n;i++)
{
cin >> a[i];
}
for (int ti = 1;ti <= q;ti++)
{
cin >> x >> y;
if (y - x > 100)
{
cout << "Yes\n";
}
else
{
for (int i = x;i <= y;i++)
{
b[i - x + 1] = a[i];
}
sort(b + 1, b + y - x + 2);
bool f = 0;
for (int i = 1;i <= y - x - 1;i++)
{
if (b[i] + b[i + 1] > b[i + 2])
{
f = 1;
break;
}
}
if (f)
{
cout << "Yes\n";
}
else
{
cout << "No\n";
}
}
}
return 0;
}
T3
给定一个长为
- 如果
o = 1 ,对序列a 中的区间[l, l + m - 1] 进行翻转。 - 如果
o = 2 ,则表示求a_l 。
保证第一种操作中的
使用印有完整 Splay 代码的文化T恤衫,秒了。
笑点解析:平板电视卡过去了。
两个关键的性质:
-
翻转操作的区间左边界不减。
-
区间长度是固定的。
可以将问题看成是一个长度为
一个翻转状态进行标记,如果区间是未翻转状态,则头出尾进,如果是翻转状态,则尾出头进。
使用双端队列维护即可。
#include<bits/stdc++.h>
using namespace std;
const int N = 1e6 + 5;
int n, m, q, a[N], b[N * 2], o, x, f, cnt = 1, l = N, ans;
int main()
{
freopen("section.in", "r", stdin);
freopen("section.out", "w", stdout);
cin >> n >> m >> q;
for (int i = 1;i <= n;i++)
{
cin >> a[i];
}
for (int i = 1;i <= m;i++)
{
b[l + i - 1] = a[i];
}
for (int ti = 1;ti <= q;ti++)
{
cin >> o >> x;
if (o == 1)
{
for (;cnt < x;cnt++)
{
if (!f)
{
a[cnt] = b[l];
b[l++ + m] = a[cnt + m];
}
else
{
a[cnt] = b[--l + m];
b[l] = a[cnt + m];
}
}
f ^= 1;
}
else
{
if (x < cnt || x >= cnt + m)
{
ans ^= a[x];
}
else
{
if (!f)
{
ans ^= b[l - cnt + x];
}
else
{
ans ^= b[l + m - 1 + cnt - x];
}
}
}
}
cout << ans;
return 0;
}
T4
给定一张包含
初始时有一个空集合
- 直接将
v 加入集合,价值为0 。 - 选择一个在集合中且与
v 有边相连的点u ,将v 加入集合,价值为a_u 。
求可以获得的最大价值和。
big胆!竟敢让我
但是
整一个
发现寄了。
一个小操作:先减去点权之和,将边权设为相邻两点权值之和,可以防止方案不合法。
#include<bits/stdc++.h>
using namespace std;
const int N = 1e3 + 5;
long long n, b[N], f[N], cnt, ans;
struct node
{
long long u, v, s;
}a[N * N * 2];
void add(int x, int y, int s)
{
a[++cnt].u = x;
a[cnt].v = y;
a[cnt].s = s;
}
bool cmp(node a, node b)
{
return a.s > b.s;
}
long long find(long long k)
{
if (f[k] == k)
{
return k;
}
return f[k] = find(f[k]);
}
int main()
{
freopen("graph.in", "r", stdin);
freopen("graph.out", "w", stdout);
cin >> n;
for (int i = 1;i <= n;i++)
{
cin >> b[i];
ans -= b[i];
}
for (int i = 1;i <= n;i++)
{
f[i] = i;
add(0, i, b[i]);
for (int j = i + 1;j <= n;j++)
{
if ((b[i] & b[j]) == 0)
{
add(i, j, b[i] + b[j]);
}
}
}
sort(a + 1, a + cnt + 1, cmp);
for (int i = 1;i <= cnt;i++)
{
if (find(a[i].u) != find(a[i].v))
{
ans += a[i].s;
f[find(a[i].u)] = find(a[i].v);
}
}
cout << ans;
return 0;
}
烂头,烂中,烂尾。