2020.09.23 北师大新生赛(三)代码
这次训练的题目还是挺有趣的吧。下面的代码都是我自己写的,可能会和官方题解不太一样,不过都是可以AC的。
P1000 超级玛丽游戏
- 直接复制粘贴输出就行
#include<cstdio>
int main() {
printf(
" ********\n"
" ************\n"
" ####....#.\n"
" #..###.....##....\n"
" ###.......###### ### ###\n"
" ........... #...# #...#\n"
" ##*####### #.#.# #.#.#\n"
" ####*******###### #.#.# #.#.#\n"
" ...#***.****.*###.... #...# #...#\n"
" ....**********##..... ### ###\n"
" ....**** *****....\n"
" #### ####\n"
" ###### ######\n"
"##############################################################\n"
"#...#......#.##...#......#.##...#......#.##------------------#\n"
"###########################################------------------#\n"
"#..#....#....##..#....#....##..#....#....#####################\n"
"########################################## #----------#\n"
"#.....#......##.....#......##.....#......# #----------#\n"
"########################################## #----------#\n"
"#.#..#....#..##.#..#....#..##.#..#....#..# #----------#\n"
"########################################## ############\n"
);
return 0;
}
CF405A Gravity Flip
- 按升序排序即可
#include<cstdio>
#include<algorithm>
using namespace std;
const int maxn = 110;
int a[maxn], N;
int main() {
scanf("%d", &N);
for (int i = 0; i < N; i++) scanf("%d", &a[i]);
sort(a, a + N);
for (int i = 0; i < N; i++) printf("%d%c", a[i], i + 1 == N ? '\n' : ' ');
return 0;
}
CF1325A EhAb AnD gCd
- 令 a = 1 , b = x − 1 a = 1, b = x - 1 a=1,b=x−1即可。
#include<cstdio>
int main() {
int T;
scanf("%d", &T);
while (T--) {
int x;
scanf("%d", &x);
printf("%d %d\n", 1, x - 1);
}
return 0;
}
CF17B Hierarchy
- 用最小生成树去做就行。只需要改变一点,就是在求最小生成树时,判断这个节点是否已经有了上司,如果有就continue.
#include<cstdio>
#include<algorithm>
using namespace std;
const int maxn = 1010, maxm = 10010;
int q[maxn], N, M, sup[maxn];
struct P {
int u, v, cost;
bool operator<(const P& rhp)const {
return cost < rhp.cost;
}
}G[maxm];
int p[maxn];
void init(int N) {
for (int i = 1; i <= N; i++) p[i] = i;
}
int find(int x) {
if (p[x] == x) return x;
return p[x] = find(p[x]);
}
void unite(int a, int b) {
if (find(a) == find(b)) return;
p[find(a)] = find(b);
}
int mst() {
init(N);
sort(G, G + M);
int cnt = 0, res = 0;
for (int i = 0; i < M; i++) {
int u = G[i].u, v = G[i].v, c = G[i].cost;
if (find(u) == find(v) || sup[v]) continue;
unite(u, v);
sup[v] = u;
res += c, cnt++;
}
if (cnt == N - 1) return res;
return -1;
}
int main() {
scanf("%d", &N);
for (int i = 0; i < N; i++) scanf("%d", &q[i]);
scanf("%d", &M);
for (int i = 0; i < M; i++) {
scanf("%d%d%d", &G[i].u, &G[i].v, &G[i].cost);
}
printf("%d\n", mst());
return 0;
}
P3200 [HNOI2009]有趣的数列
- 我们把1, 2, 3, … , 2N 这 2N 个数字依次摆到序列上面,可以按照这样的规则:
- 奇数位置的数字,按照顺序摆,即必须先摆 a 2 i − 1 a_{2i-1} a2i−1,再摆 a 2 i + 1 a_{2i+1} a2i+1. 偶数也是,必须按照顺序摆,先摆 a 2 i a_{2i} a2i 再摆 a 2 i + 2 a_{2i+2} a2i+2. 这样就满足了前两个条件。
- 第三个条件这样满足,我们在摆数字的时候,如果摆在奇数位置,记为0;摆在偶数位置记为1. 这样我们又生成了一个01序列。那么这个01序列,只要任意前缀和0的数量不少于1的数量,那么生成的那个序列就是符合要求的。
- 因此,答案就是卡特兰数 C 2 n n n + 1 \frac{C_{2n}^{n}}{n+1} n+1C2nn。
- 但是,这个题还有一个难点,就是P不是质数,不能有逆元和卢卡斯定理,不过可以这样, h ( n ) = C 2 n n − C 2 n n − 1 = C 2 n n n + 1 = ( 2 n ) ! ( n + 1 ) ! ∗ n ! h(n)=C_{2n}^{n}-C_{2n}^{n-1}=\frac {C_{2n}^{n}}{n+1} = \frac{(2n)!}{(n+1)!*n!} h(n)=C2nn−C2nn−1=n+1C2nn=(n+1)!∗n!(2n)!,然后阶乘分解质因数,再乘起来就好。
- 一定要小心,数组maxn的范围开到2e6!
#include<cstdio>
#include<algorithm>
using namespace std;
const int maxn = 2000010;
int prime[maxn], cnt;
bool st[maxn];
int N, P, ex[maxn];
typedef long long ll;
void sieve(int N) {
for (int i = 2; i <= N; i++) {
if (!st[i]) prime[cnt++] = i;
for (int j = 0; prime[j] <= N / i; j++) {
st[prime[j] * i] = true;
if (i % prime[j] == 0) break;
}
}
}
int get(int p, int n) {
int res = 0;
while (n) {
res += n / p;
n /= p;
}
return res;
}
ll mod_pow(ll x, ll n) {
ll res = 1;
while (n) {
if (n & 1) res = res * x % P;
x = x * x % P;
n >>= 1;
}
return res;
}
int main() {
sieve(maxn - 1);
scanf("%d%d", &N, &P);
for (int i = 0; i < cnt; i++) {
int p = prime[i];
ex[i] = get(p, 2 * N) - get(p, N + 1) - get(p, N);
}
ll ans = 1;
for (int i = 0; i < cnt; i++) {
ans = ans * mod_pow((ll)prime[i], (ll)ex[i]) % (ll)P;
}
printf("%lld\n", ans);
return 0;
}