csu-2018年11月月赛Round2-div2题解
csu-2018年11月月赛Round2-div2题解
A(2193):昆虫繁殖
Description
科学家在热带森林中发现了一种特殊的昆虫,这种昆虫的繁殖能力很强。每对成虫过x个月产y对卵,每对卵要过两个月长成成虫。假设每个成虫不死,第一个月只有一对成虫,且卵长成成虫后的第一个月不产卵(过X个月产卵),问过Z个月以后,共有成虫多少对?0=<X<=20,1<=Y<=20,X=<Z<=50
Input
单组数据 x,y,z的数值
Output
过Z个月以后,共有成虫对数
Sample Input
1 2 8
Sample Output
37
题解:
从x+1到z+1循环,设a[i]为第i个月成虫的数量,b[i]为第i个月卵的数量。所以a[i] = a[i - 1] + b[i - 2](卵两个月长成成虫),b[i] = y * a[i - x](过x月产y对卵),则a[z + 1]就是答案。
初始条件为从1到x,a[i] = 1, b[i] = 0;
注意x == 0时,i初始值为1,b[i - 2] 会数组越界,这时单独判断一下。
代码:
#include<bits/stdc++.h>
typedef long long ll;
using namespace std;
inline ll getnum() {
ll ans = 0; char c; ll flag = 1;
while (!isdigit(c = getchar()) && c != '-');
if (c == '-') flag = -1; else ans = c - '0';
while (isdigit(c = getchar())) ans = ans * 10 + c - '0';
return ans * flag;
}
ll a[100], b[100];
int main() {
ll x = getnum(), y = getnum(), z = getnum();
a[1] = 1;
for (int i = 1; i <= x; i++) {
a[i] = 1;
b[i] = 0;
}
for (int i = x + 1; i <= z + 1; i++) {
if (i == 1) {
a[i] = 1;
}
else a[i] = a[i - 1] + b[i - 2];
b[i] = y * a[i - x];
}
if (x == z) {
cout << "1";
}
else cout << a[z + 1];
return 0;
}
B(2194):小车问题
Description
甲、乙两人同时从A地出发要尽快同时赶到B地。出发时A地有一辆小车,可是这辆小车除了驾驶员外只能带一人。已知甲、乙两人的步行速度一样,且小于车的速度。问:怎样利用小车才能使两人尽快同时到达。
Input
仅一行,三个数据分别表示AB两地的距离s,人的步行速度a,车的速度b。
Output
两人同时到达B地需要的最短时间(保留三位小数)。
Sample Input
120 5 25
Sample Output
9.600
题解:
数学题,同时到达时间最短,则走路的和开车的同时到达。设一开始开车送第一个走的距离为x,剩下距离为s - x,则答案就为x / b + (s - x) / a,把x解出来即可
解出来之后为:
有个公因式b-a,所以x就等于(b + a) * s / (b + 3 * a)
代码:
#include<bits/stdc++.h>
#define maxn 1070
using namespace std;
inline int getnum() {
int ans = 0; char c; int flag = 1;
while (!isdigit(c = getchar()) && c != '-');
if (c == '-') flag = -1; else ans = c - '0';
while (isdigit(c = getchar())) ans = ans * 10 + c - '0';
return ans * flag;
}
int main() {
double s = getnum(), a = getnum(), b = getnum();
double x = (b + a) * s / (b + 3 * a);
printf("%.3lf\n", x / b + (s - x) / a);
return 0;
}
C(2196):Lights
Memory Limit: 2 Mb
Description
xrdog有个灯泡,编号从1到N。灯泡在一开始的时候都是亮着的,xrdog会对这些灯泡进行次操作,每一次操作都会选择一盏灯,并把除了这盏灯以外的灯的开关都按一下(即除了这盏灯以外的所有亮着的灯变成暗的,暗的灯变成亮的)
有趣的是,xrdog只会进行奇数次操作(即),并且最终有且仅有一盏灯是亮着的。
小砖对xrdog的这一系列操作十分的好奇,她很想知道最后亮着的这一盏灯是哪一盏。所以你能帮助一下她嘛?
Input
第一行两个整数 N(1<=N<=1018)N(1<=N<=1018) 和 M(1<=M<=106)M(1<=M<=106)
接下来一行 MM 个整数表示次操作一次是选择的哪一盏灯
Output
打印一个整数,表示最后亮着的灯的编号。
Sample Input
46 3
1 13 1
Sample Output
13
题解:
因为最后保证只有一盏灯,进行奇数次操作,所以对于某一盏灯的操作次数必须要为偶数次,否则这个灯最后就会处于打开状态,观察到空间只有2mb,不能存下来找那些是奇数次,所以对于每次操作直接对当前状态求异或即可,因为若进行偶数次操作异或结果为0,达到了找匹配的效果。
代码:
#include<bits/stdc++.h>
typedef long long ll;
using namespace std;
inline ll getnum() {
ll ans = 0; char c; int flag = 1;
while (!isdigit(c = getchar()) && c != '-');
if (c == '-') flag = -1; else ans = c - '0';
while (isdigit(c = getchar())) ans = ans * 10 + c - '0';
return ans * flag;
}
int main() {
ll n = getnum(), m = getnum();
ll ans = 0;
for (int i = 1; i <= m; i++) {
ll x = getnum();
ans ^= x;
}
cout << ans;
return 0;
}
D(2204):漫无止境的八月
Description
又双叒叕开始漫无止境的八月了,阿虚突然问起长门在这些循环中团长哪几次扎起了马尾,他有多少次抓住了蝉等等问题,长门一共回复n个自然数,每个数均不超过1500000000(1.5*10^9)。已知不相同的数不超过10000个,现在需要统计这些自然数各自出现的次数,并按照自然数从小到大的顺序输出统计结果。
Input
第1行是整数n,表示回复的自然数的个数。n<=1e6
第2~n+1行每行一个自然数。
Output
包含m行(m为n个自然数中不相同数的个数),按照自然数从小到大的顺序输出。每行输出两个整数,分别是自然数和该数出现的次数,其间用一个空格隔开。
Sample Input
8
2
4
2
4
5
100
2
100
Sample Output
2 3
4 2
5 1
100 2
水题,直接贴代码:
#include<bits/stdc++.h>
#define maxn 1000050
using namespace std;
int a[maxn];
inline int getnum() {
int ans = 0; char c; int flag = 1;
while (!isdigit(c = getchar()) && c != '-');
if (c == '-') flag = -1; else ans = c - '0';
while (isdigit(c = getchar())) ans = ans * 10 + c - '0';
return ans * flag;
}
int lis[maxn];
int main() {
int n = getnum();
for (int i = 1; i <= n; i++) {
a[i] = getnum();
}
sort(a + 1, a + n + 1);
int cnt = 1;
if (n == 1) {
cout << a[1] << " " << "1" << endl;
}
for (int i = 2; i <= n; i++) {
if (a[i] == a[i - 1]) {
cnt++;
if (i == n) {
cout << a[i] << " " << cnt;
}
}
else {
cout << a[i - 1] << " " << cnt << endl;
if (i == n) {
cout << a[i] << " " << "1";
}
cnt = 1;
}
}
return 0;
}
E(2205):Magia
Description
吼姆啦酱来救被变成魔女的纱耶香攻击的小圆辣!魔境背景中的指挥家指挥着这场表演的音乐,吼姆啦酱发现一个规律,如果过一串音符是回文的,那么这串音符会实物化来攻击她,现在给出一段音符,判断它是否是回文的。一个左右对称的自然数称为回文数,即这个数从左往右读与从右往左读是一样的,如121,686,13731,8668等都是回文数。
Input
输入一个int范围内的自然数N,判断它是否是回文数。如果是就输出这个回文数,若不是则输出-1。
Output
只有一行,N是回文数,就输出N,不是就输出-1。
Sample Input
686
Sample Output
686
更水,直接贴代码:
#include<bits/stdc++.h>
using namespace std;
char s[10000];
int main() {
scanf("%s", s + 1);
int len = strlen(s + 1);
int x;
if (len % 2 == 1) {
x = (len - 1) / 2;
}
else x = len / 2;
bool flag = true;
for (int i = 1; i <= x; i++) {
if (s[i] != s[len - i + 1]) {
flag = false;
break;
}
}
if (flag) printf("%s",s + 1);
else cout << "-1";
return 0;
}