一个人抛了三个骰子,它们的顶面分别是。求它们的底面之和。
这里用的骰子是标准骰子,即两个相对的面之和为。
输出答案。
答案 | |||
---|---|---|---|
因为两个相对的面之和为,所以本题的答案为。
#include <cstdio>
using namespace std;
int main()
{
int a, b, c;
scanf("%d%d%d", &a, &b, &c);
printf("%d\n", 21 - a - b - c);
return 0;
}
给定一个由0
、1
、6
、8
、9
组成的字符串。将其旋转并输出。
一个字符串旋转的方法:
- 将其翻转(
reverse
)。- 将其中的
6
替换为9
,9
替换为6
。
输出旋转后的字符串。
输出 | |
---|---|
0601889 |
6881090 |
86910 |
01698 |
01010 |
01010 |
本题直接按要求模拟即可。
#include <cstdio>
#define maxn 100005
using namespace std;
char s[maxn];
int main()
{
int n = 0;
char c;
while((c = getchar()) != '\n')
s[n++] = c;
while(n--)
putchar(s[n] == '6'? '9': s[n] == '9'? '6': s[n]);
putchar('\n');
return 0;
}
给定三个长度为的序列:。
有多少对符合?
输出符合的的对数。
3
1 2 2
3 1 2
2 3 2
4
对符合条件:。
4
1 1 1 1
1 1 1 1
1 2 3 4
16
所有都符合条件。
3
2 3 3
1 3 3
1 1 1
0
没有符合条件。
我们很容易想到的算法:暴力枚举所有,并统计符合条件的对数。
可惜,这样会TLE
。
我们考虑将所有的和分别放入两个桶和。
根据乘法原理我们得出答案为。
注意:不要忘记使用long long
!
#include <cstdio>
#define maxn 100005
using namespace std;
using LL = long long;
int acnt[maxn], b[maxn], bcnt[maxn];
int main()
{
int n;
scanf("%d", &n);
for(int i=0; i<n; i++)
{
int a;
scanf("%d", &a);
acnt[a] ++;
}
for(int i=0; i<n; i++)
scanf("%d", b + i);
for(int i=0; i<n; i++)
{
int c;
scanf("%d", &c);
bcnt[b[--c]] ++;
}
LL ans = 0LL;
for(int i=1; i<=n; i++)
ans += LL(acnt[i]) * LL(bcnt[i]);
printf("%lld\n", ans);
return 0;
}
在由个a
和个b
(均不要求连续)组成的字符串中,求字典序第小的。
(为由个a
和个b
组成的字符串的个数)
输出由个a
和个b
组成的字符串中字典序第小的。
输出 | |||
---|---|---|---|
baab |
|||
(个b 个a ) |
我们令为由个a
和个b
组成的字符串的个数,则:
a
或b
:我们令为由个a
和个b
组成的字符串中字典序第小的字符串,则有如下递推式(这里的加法表示字符串连接):
写代码时,可以用递归形式,也可以使用非递归形式(更快):
#include <cstdio>
#define maxn 35
using namespace std;
using LL = long long;
LL dp[maxn][maxn];
int main()
{
int a, b;
LL k;
scanf("%d%d%lld", &a, &b, &k);
for(int i=0; i<=a; i++) dp[i][0] = 1;
for(int i=0; i<=b; i++) dp[0][i] = 1;
for(int i=1; i<=a; i++)
for(int j=1; j<=b; j++)
dp[i][j] = dp[i - 1][j] + dp[i][j - 1];
while(a && b)
{
LL t = dp[a - 1][b];
if(k <= t) putchar('a'), a --;
else putchar('b'), b --, k -= t;
}
while(a--) putchar('a');
while(b--) putchar('b');
putchar('\n');
return 0;
}
我们有一棵个节点的树,节点的编号分别为。
号点是根节点,且第个点()的父亲节点是。
给你个查询,第个查询包含两个整数和,求符合下列条件的点的个数:
输出行。第行包含对第个查询的回应。
7
1 1 2 2 4 2
4
1 2
7 2
4 1
5 5
3
1
0
0
在第一个查询中,节点符合条件。
在第二个查询中,只有节点符合条件。
在最后两个查询中,没有节点符合条件。
我们可以先在整棵树上从根节点开始跑一遍,对于节点预处理出和,分别表示进入和走出这个节点的时间,同时将第层节点的所有放入。
如果节点到根节点的路径中有,则。
因此,对于每个查询,我们利用二分查找即可快速算出符合条件的节点个数。
#include <cstdio>
#include <vector>
#include <algorithm>
#define maxn 200005
using namespace std;
int in[maxn], out[maxn], dep[maxn], cnt;
vector<int> G[maxn], depin[maxn];
void dfs(int v)
{
depin[dep[v]].push_back(in[v] = cnt++);
for(int u: G[v])
dfs(u);
out[v] = cnt++;
}
int main()
{
int n;
scanf("%d", &n);
dep[0] = cnt = 0;
for(int i=1; i<n; i++)
{
int p;
scanf("%d", &p);
dep[i] = dep[--p] + 1;
G[p].push_back(i);
}
dfs(0);
int q;
scanf("%d", &q);
while(q--)
{
int u, d;
scanf("%d%d", &u, &d);
const auto& din = depin[d];
auto first = lower_bound(din.begin(), din.end(), in[--u]);
auto last = lower_bound(din.begin(), din.end(), out[u]);
printf("%lld\n", last - first);
}
return 0;
}