7 21 第一次团队赛——————写给队友
希望队友认真看完 这可是我花了一晚上的时间写的呢
按照出题的顺序 写的
A题:
给出两个数 n, m。求 和 。
计算公式:
Input
输入数据有多组(数据组数不超过 250),到 EOF 结束。
对于每组数据,输入两个用空格隔开的整数 n, m (0 <= m <= n <= 20) 。
Output
对于每组数据输出一行, 和 ,用空格隔开。
Sample Input
1 1
5 3
4 3
Sample Output
1 1
60 10
24 4
当时我们交的代码(一遍过,只不过时间有点长……)
#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <cstring>
using namespace std;
int main()
{
long long int a,b,i;
while(scanf("%lld%lld",&a,&b)!=EOF)
{
long long int s=1,s2=1,s1=1,s3=1;
for(i=a;i>=1;i--)
s*=i;
for(i=a-b;i>=1;i--)
s1*=i;
for(i=b;i>=1;i--)
s3*=i;
printf("%lld %lld\n",s/s1,s/s1/s3);
}
return 0;
}
下面是我的代码(已AC)
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstdlib>
#include <cstring>
#include <deque>
using namespace std;
typedef long long ll;
deque <ll> dq;
int main()
{
ll n,m,a[21],c,d,i;
a[0]=1;
for(i=1;i<=20;i++)
a[i]=a[i-1]*i;
while(~scanf("%lld%lld",&n,&m))
{
c=a[n]/a[n-m];
d=c/a[m];
printf("%lld %lld\n",c,d);
}
return 0;
}
C题
UMR 现在手里有 n 张康纳的表情,最上面一张是玛吉呀巴库乃。现在 UMR 如果每次把最上面的 m 张牌移到最下面而不改变他们的顺序及朝向,那么至少经过多少次移动玛吉呀巴库乃才会又出现在最上面呢?
Input
多组输入。
对于每组数据,输入以空格分隔的两个整数 n 和 m (1 <= n, m <= 10^9)。
Output
对于每组数据,输出一个整数,表示至少移动的次数。
Sample Input
54 12
Sample Output
9
当时我们是想复杂了 用的队列做 时间超限
先解释一个地方 双端对列 1 2 3 4 5从前往后进队列 问现在从后往前看 队列的顺序 答案是5 4 3 2 1
下面是时间超限的代码
#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <cstring>
#include <deque>
using namespace std;
deque<long long int> dp;
int main()
{
long long int a,b;
while(scanf("%lld%lld",&a,&b)!=EOF)
{
while(!dp.empty())
{
dp.pop_front();
}
long long int s=0,i,x;
for(i=1;i<=a;i++)
{
dp.push_back(i);
}
x=dp.front();
for(i=1;i<=b;i++)
{
dp.push_back(dp.front());
dp.pop_front();
}
s++;
for(i=0;;i++)
{
if(i%b==0)
{
if(x==dp.front())
break;
else
s++;
}
dp.push_back(dp.front());
dp.pop_front();
}
printf("%lld\n",s);
}
return 0;
}
其实这个题是规律 我们是先写出来然后多组输入找的规律,规律是看a是不是跟b有公约数 如果是有答案是a/最大公约数,不是就是本身,下面是对的代码
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstdlib>
#include <cstring>
#include <deque>
using namespace std;
typedef long long ll;
deque <ll> dq;
int main()
{
ll a,b,c;
while(~scanf("%lld%lld",&a,&b))
{
c=__gcd(a,b);
if(c==1)
printf("%lld\n",a);
else
printf("%lld\n",a/c);
}
return 0;
}
H题(博弈)(一遍过)
C~K 和 PBH 经常玩一个游戏。游戏规则如下:现给定一个 n*n 的棋盘,一个石头被放在棋盘的左上角。
他们轮流移动石头。每一回合,两个人只能把石头向上,下,左,右四个方向移动一格,并且要求移动到的格子之前不能被访问过。谁不能移动石头了就算输。
假如 C~K 先移动石头,而且 C~K 和 PBH 都足够聪明,那么最后谁能赢?
Input
多组输入。
每组输入输入第一行包含一个整数 n (1 <=n <= 1e9),表示棋盘的规模。
当输入 n 为 0 时,输入结束。
Output
对于每组数据,如果 C~K 最后能赢,则输出 "C~K",否则输出 "PBH",每一组答案独占一行,输出不包括引号。
Sample Input
2
0
Sample Output
C~K
规律特别简单,偶数先手赢 奇数后手赢
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstdlib>
#include <cstring>
#include <deque>
using namespace std;
typedef long long ll;
deque <ll> dq;
int main()
{
ll a;
while(~scanf("%lld",&a))
{
if(a==0)
break;
if(a%2==0)
printf("C~K\n");
else
printf("PBH\n");
}
return 0;
}
J 题 当时没有做出来
这一天希酱又补了一卦,没想到每个人都发到了一张印有整数的牌,现在希酱想要继续占卜的话需要知道每个人手里拿的牌的整数具体是多少,但是她们却打起了哑谜。
穗乃果:我拿到的是 2 的倍数哦~
绘里:我拿到的是奇数啦~
南小鸟:花阳拿的比我大
花阳:妮可拿的是我的两倍
海未:我拿的数字各位数字之和加起来是 3 的倍数
真姬:绘里比我拿的小
希:我们 9 个人拿的数字范围是 [1, 9]
凛:我拿的数字和真姬的一样~
妮可:我拿的数字要比 1 大呢
希酱感到非常的无奈,不过希酱可以通过对符合条件的情况种类数进行一系列占卜来一个个确定出她们的具体数字。但是希一个个去考虑情况数太难了,所以,你来帮帮她吧~
Input
没有输入。
Output
输出一个整数,表示符合 9 个人描述的情况的所有可能的种类数。
澄清一下 我们的思路没有问题 对希那句话理解的也没有错 没必要一定有1有9
下面是当时的代码(不对)
#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <cstring>
#include <deque>
using namespace std;
int main()
{
long long int s=0,s1=0,i,j,l;
for(i=1;i<=9;i++)//hui
{
if(i%2!=0)
{
for(j=1;j<=9;j++)//zhenji+lin
{
if(j>i)
{
s1++;
}
}
}
}
for(i=2;i<=9;i++)//nike
{
for(j=1;j<=9;j++)//huayang
{
if(i/j==2&&i%2==0)
{
for(l=1;l<=9;l++)//nan
{
if(j>l)
s++;
}
}
}
}
printf("%lld\n",s*s1*4*3*9);
return 0;
}
终于找到问题了 就差那么一点点 思路绝对没有问题 这是AC的代码 就差一个i%j==0,当时只考虑i整除j 竟然忘了是否整除
#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <cstring>
#include <deque>
using namespace std;
int main()
{
long long int s=0,s1=0,i,j,l;
for(i=1;i<=9;i++)//huili
{
if(i%2!=0)
{
for(j=1;j<=9;j++)//zhenji+lin
{
if(j>i)
{
s1++;
}
}
}
}
for(i=2;i<=9;i++)//nike
{
for(j=1;j<=9;j++)//huayang
{
if(i/j==2&&i%2==0&&i%j==0)
{
for(l=1;l<=9;l++)//nan
{
if(j>l)
{
s++;
}
}
}
}
}
printf("%lld\n",s*s1*4*3*9);
return 0;
}
下面是当时没时间看的题(就是不会)
B 题
486 作为有史以来最悲惨的男主,我们知道他需要经历一些无限次的死亡和轮回才能进行下一个关卡。
现在给你 n 个连续的时间点,每个时间点 i 上都会有一个心理伤害值 hurt[i],然后告诉你 m 个死亡时间点 deth[i],以及当前死亡时间点会死亡的次数 num[i],和死亡后 486 会返回的时间点(也就是最近的存档点 return[i])。
其整个过程就是 486 从时间点 0 开始 (hurt[0] = 0),不断向下一个时间点 1, 2, 3… 前进,当遇到死亡时间点的时候,486 会死亡一次,然后返回到最近的一个存档点,然后会继续从存档点向下一个时间点前进,当又遇到死亡时间点的时候,如果死亡次数还不够需要死亡的次数,那么当前不能过关,继续回到最近的存档点。达到需要死亡的次数之后,便不需要死亡,继续向下一个时间点前进。486 在每一个时间点 i 上都会遭受心理伤害 hurt[i]。为什么 486 的心理防线不会崩溃呢,当然因为有我们的蕾姆酱了,每次受到心理伤害的时候蕾姆酱都会治愈掉。第一季的目标便是走到时间点 n,现在需要你计算一下蕾姆酱的治愈总和(也就是 486 从时间点 0 到时间点 n 所遭受的心理攻击的总和)。
那么萌萌的蕾姆酱到底治愈了多少呢~她这么萌,你还不快告诉她么~
Input
输入数据有多组(数据组数不超过 30),到 EOF 结束。
对于每组数据:
- 第一行输入两个以空格分隔的整数 n 和 m
- n (1 <= n <= 100000) 表示 486 要到达的目标时间点(起始目标点 0,hurt[0] = 0,每次前进一个时间点)
- 接下来一行输入 n 个以空格分隔的整数,表示 hurt[i]。表示 486 在当前时间点会遭受到的伤害值
- 接下来输入 m (0 <= m <= n/2) 行,每行 3 个整数,分别是 deth[i],return[i] 和 num[i],表示 deth[i] 时间点需要死亡的次数以及会返回的最近的存档点
保证:0 <= hurt[i] <= 100,1 <= deth[i-1] < return[i] < deth[i] <= n, 0 <= num[i] <= 100。
当前时间点如果不需要死亡,那么486不会返回最近的存档点,会继续前进。
Output
对于每组数据,输出一个整数,表示蕾姆酱总的治愈值(486 会遭受到的总的伤害值)。
Sample Input
10 3
1 2 3 4 5 5 4 3 2 1
4 2 1
6 5 2
10 9 1
Sample Output
62
题意自己看 仔细点
思路:hurt是伤害值,从头开始要走到结尾结束 直接暴力就好 每次经过num不是0的点要num--,注意不能直接赋0(原因看题意),返回他要返回的点,还要注意 输入时不能直接num[i],deth[i],return[i],必须num[deth],return[deth]
下面是代码
#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <cstring>
#include <deque>
using namespace std;
typedef long long ll;
ll hurt[101000],deth,returnn[101000],num[101000];
int main()
{
ll i,sum=0,n,m,e=0;
while(~scanf("%lld%lld",&n,&m))
{
memset(hurt,0,sizeof(hurt));
memset(num,0,sizeof(num));
memset(returnn,0,sizeof(returnn));
sum=0;e=1;
for(i=1;i<=n;i++)
scanf("%lld",&hurt[i]);
for(i=1;i<=m;i++)
{
scanf("%lld",&deth);
scanf("%lld%lld",&returnn[deth],&num[deth]);
}
for(i=0;i<=n;i++)
{
if(num[i]==0)
sum+=hurt[i];
else
{
sum+=hurt[i];
num[i]--;
i=returnn[i]-1;
}
}
printf("%lld\n",sum);
}
return 0;
}
G题(贪心)
snow 是个热爱打字的家伙,每次敲出更快的速度都会让他很开心。现在,他拿到一篇新的打字文章,已知这篇文章只有 26 个小写英文字母,给出 snow 打出这 26 个英文字母分别需要多少时间 (s),问 snow 打完这篇文章获得的 kpm(打正确的字数/所花的分钟数)最大为多少?
注意 snow 可能会打错一些字哦。打错的必定是文章里面存在的。
Input
多组输入。
对于每组数据,首先输入 26 个整数,分别表示打出 a, b, c, ..., z 这 26 个字母需要的时间(保证是 int 范围内的正整数),然后给出一个字符串,长度不超过 1000,保证只包含小写英文字母。
Output
对于每组数据,输出一行,表示最大的 kpm,保留 2 位小数。
Sample Input
1 2 2 1 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
abcd
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
abcd
Sample Output
40.00
25.71
思路:要使kpm最大 必须使分子尽可能大,(含故意打错的可能)分母尽可能小 看代码 含备注
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
typedef long long ll;
int main()
{
ll i,n;
char s[1010];
double a[26],sum=0,ans=0,t[1010];
while(~scanf("%lf",&a[0]))
{
sum=0,ans=0;
for(i=1; i<26; i++)
scanf("%lf",&a[i]);
getchar();
gets(s);
n=strlen(s);
for(i=0; i<n; i++)
t[i]=a[s[i]-'a'];
sort(t,t+n);//排序 使t[0]最小 t[n]最大
for(i=0; i<n; i++)
sum+=t[i];//算出总和
ans=(double)n*60.0/sum;
while(n--)//n是在不断变化的
{
sum-=t[n];//每次减去最大的
sum+=t[0];//故意打错最大的,强制输入最小的
ans=max(ans,(double)n*60.0/sum);
}
printf("%.2lf\n",ans);
}
return 0;
}