2021.11.27【提高组】模拟赛C组
T1.蚂蚁
Description:
n只蚂蚁以每秒1cm的速度在长为Lcm的竿子上爬行。当蚂蚁爬到竿子的端点时就会掉落。由于竿子太细,两只蚂蚁相遇时,它们不能交错通过,只能各自反向爬回去。对于每只蚂蚁,我们知道它距离竿子左端的距离xi,但不知道它当前的朝向。请计算各种情况当中,所有蚂蚁落下竿子所需的最短时间和最长时间。
Input:
第一行:N,L
后N行 每行一个Ai,表示位置
Output:
最短时间和最长时间
Solution:
最短时间的计算,可以算出每只蚂蚁距离两端点最近的距离,也就是比较到左端点和右端点的距离,最短时间即为所有蚂蚁的到其最近端点的距离中的最大值
最长时间同理,即为每只蚂蚁到其最远端点的距离中的最大值
题目中提到两只蚂蚁相撞之后会反方向爬,其实这是可以忽略的,相撞之后可以视为两蚂蚁交换位置后继续向原方向走
Code:
#include <stdio.h>
#include <iostream>
#include <cmath>
#include <cstring>
#define N 1000000
#define re register
#define ll long long
using namespace std;
ll n, l, a[N], ans1, ans2;
signed main () {
//freopen("t1.in", "r", stdin);
//freopen("t1.out", "w", stdout);
scanf("%lld %lld", &n, &l);
for (re ll i (1); i <= n; ++ i) {
scanf("%lld", &a[i]);
ans1 = max(ans1, min(a[i], l - a[i]));
ans2 = max(ans2, max(a[i], l - a[i]));
}
printf("%lld %lld", ans1, ans2);
}
T2 max:
Description:
一个正整数一般可以分为几个互不相同的自然数的和,如3=1+2,4=1+3,5=1+4=2+3,6=1+5=2+4,…。
现在你的任务是将指定的正整数n分解成m个(m>=1)互不相同的自然数的和,且使这些自然数的乘积最大。
Input:
N(N <= 10000)
Output:
第一行是分解方案,相邻的数之间用一个空格分开,并且按由小到大的顺序。
第二行是最大的乘积。
Solution:
1:(80pts)我们可以发现,只要被拆分出来的数,差尽可能的小,就可以做到积最大,同时要避免出现1,因为1不仅占了一个数的位置,还对积的大小没有任何贡献,所以我们可以从2开始装入答案,每次加1,直到总和超过N,最后可能会出现超过N的情况,于是我们可以去掉一个数,使得剩下来的总和正好等于N,去掉的数即为total - N,若我们用一个数组来存每个拆分出来的数,则他的下标为total - N - 1(从2开始装入,故所有数对应的下标为它本身-1),当然该方法弊端很明显,我们不能确保每次都有一个数用总和减去后都正好等于N,也就是说减去后可能会导致总和小于N
主要部分代码如下:
for (re ll i (2); ; ++ i) {
if (tot >= n) {
break;
}
a[++ t] = i;
tot += i;
}
a[tot - n - 1] = 0;
for (re ll i (1); i <= t; ++ i) {
if (a[i] != 0) {
time(a[i]);
printf("%lld ", a[i]);
}
}
2.(100pts)该方法就是在第一种方法的基础上,在删除数的部分加以改动,首先我们不一定能找到一个减去后正好等于N的数,所以我们枚举先列出来的数,找到用总和减去后与N差距最小的一个(若存在减去后等于N的则直接删去那个),删去那个找到的数(即赋为0),然后就会出现总和小于N的情况,此时就可以算出总和与N的差(min),然后从后往前将每个数都加1,直到分完min个
最后,由于答案较大,需要加高精度累乘
Code:
#include <stdio.h>
#include <iostream>
#include <cmath>
#include <cstring>
#include <algorithm>
#define N 10000000
#define re register
#define ll long long
using namespace std;
ll n, a[N], t, tot, ans1[N], w = 1, xx, minc = 1e15, idx;
bool wz = false;
void time(int x) {
for(re ll i (1); i <= w; ++ i) {
ans1[i] = ans1[i] * x;
}
for(re ll i (1); i <= w; ++ i) {
if(ans1[i] >= 10) {
xx = ans1[i] / 10;
ans1[i + 1] += xx;
ans1[i] %= 10;
w = max(w, i + 1);
}
}
}
signed main () {
// freopen("max.in", "r", stdin);
// freopen("max.out", "w", stdout);
scanf("%lld", &n);
ans1[1] = 1;
for (re ll i (2); ; ++ i) {
if (tot >= n) {
break;
}
a[++ t] = i;
tot += i;
}
if (tot != n) {
for (re int i (1); i <= t; ++ i) {
if (tot - a[i] == n) {
a[i] = 0;
tot -= a[i];
wz = true;
} else if (abs((tot - a[i]) - n) < minc) {
minc = abs((tot - a[i]) - n);
idx = i;
}
}
if (wz == false) {
tot -= a[idx];
a[idx] = 0;
}
if (tot < n) {
for (re int i (n); i >= 1; -- i) {
if (a[i] != 0 and minc != 0) {
a[i] ++;
minc --;
}
}
}
}
for (re ll i (1); i <= t; ++ i) {
if (a[i] != 0) {
time(a[i]);
printf("%lld ", a[i]);
}
}
printf("\n");
for (re ll i (w); i >= 1; -- i) {
printf("%lld", ans1[i]);
}
}
T3 围攻:
Description:
经过刘邦的严密缉查,项羽的位置也就水落石出了。刘邦便趁机集合军队,进行对项羽的围攻。为了增加胜率,张良研究出一种全新的战法,目的就是一举打败难缠的项羽。
这种军队共有N个单位,一个接着一个排成一排,每个单位可以是士兵,或者是战车,这样的组合可以爆发出意想不到的强大战斗力;但有一点,两辆战车不能相邻,否则会发生剐蹭等不好的事故。刘邦希望知道这N个单位的军队都多少种不同的排列方法,以便在战场中随机应变。两种军队的排列方法是不同的,当且仅当某一个单位对应不同,如:第i位这种是士兵,那种是战车……
Input:
N
Output:
方案数(取模10^8+7)
Solution:
1.(70pts) 可以dp推导,用f[i][0]表示第i个位置放人的方案数,f[i][1]表示第i位放车的方案数,放人的没有限制,于是第i位方案数为i-1位放人和放车的方案数的和
(f[i][0] = f[i - 1][0] + f[i - 1][1])
而车不能连着放,所以他只能等于i-1的位置上放人的方案数
以下为主要代码:
f[1][1] = f[1][0] = 1;
for (int i = 2; i <= n; ++ i) {
f[i][0] = f[i - 1][1] + f[i - 1][0];
f[i][1] = f[i - 1][0];
}
如果我们多尝试几个数据,就会发现其实这是个斐波那契数列!
于是就有了一下代码:
#include <stdio.h>
#include <iostream>
#include <cmath>
#include <cstring>
#define re register
#define ll long long
#define MOD 100000007
#pragma GCC optimize("Ofast")
using namespace std;
ll n, a = 2, b = 3, c;
signed main () {
// freopen("siege.in", "r", stdin);
// freopen("siege.out", "w", stdout);
scanf("%lld", &n);
n = (n - 1) % 200000016 + 1;
switch(n) {
case 1: printf("2"); return 0;
case 2: printf("3"); return 0;
}
for (re ll i (3); i <= n; ++ i) {
c = (a + b) % MOD;
a = b % MOD;
b = c % MOD;
}
printf("%lld", c);
}