文章目录
前言
这次的题目因为知识点全面,所以难度比较大,下场难度大概还会和这个相似
一、海绵宝宝(简单)
这道本来是打算让大家签个到的,但是可能学长们讲的不是很好,所以大家都不会打…
代码如下(示例):
#include <bits/stdc++.h>//万能头文件
using namespace std;
struct stu
{
char s[20];
long long m;
long long wei;
} an[100005];
bool cmp(stu x, stu y)//比较函数
{
if (x.m == y.m)
{
return x.wei < y.wei;//排输入顺序
}
else
{
return x.m > y.m;//排分数
}
}
int main()
{
int n, m;
cin >> n;
for (int i = 1; i <= n; i++)
{
cin >> an[i].s >> an[i].m;//输入字符串和分数用cin输入字符串会比较方便
an[i].wei = i;
}
sort(an + 1, an + 1 + n, cmp);
for (int i = 1; i <= n; i++)
{
cout << an[i].s << endl;
}
}
二、派大星与海绵绵宝宝的较量(签到)
一道博弈题,当1时,先手取一个就赢了,2时,先手取2个就赢了,3时,怎么取都会输,4时,只要先取一个,让他变成3,那么对面怎么都会输,于是就赢了,照着这么写下去不难发现,当N%3等于零时,才会是派大星胜利(然后注意他的大小,要开long long)
代码如下(示例):
#include<stdio.h>
long long n,t;
int main() {
scanf("%lld",&t);
while(t--){
scanf("%lld",&n);
if(n%3) printf("Spongebob\n");
else printf("Patrick Star\n");
}
return 0;
}
三、章鱼哥的数学生活(防AK)
也是博弈,但是这个比较困难了。
#include <stdio.h>
/*思路:
首先结束时为质数且我们易知质数是奇数(除2)。
一.奇数的情况:奇数的因子必定为奇数所以减去后为偶数,由后 二 可以此情况必败
(且此偶数必定不是2^k这种形式,因为之前的奇数可拆为奇*奇,减去奇后变为奇*偶,不会是偶*偶(2^k))。
二.偶数的情况:
1.非2^k形式(可拆为奇*偶);那么只需要减去这个奇因子就会变为奇*(偶-1)即 奇*奇
由此可得此情况必胜,因为给对方的奇数情况必定会再以偶数情况回到自己手里
那么对方一直那奇数,你一直拿偶数,对方必败(该数字一直减小且到质数停止)。
2.为2^k形式(可拆为偶*偶):我们可以想一下这种情况可以减到什么情况,他只能减2^(k-1)到2^(k-1) (2^k形式)
或者减其他因子到(奇*偶),那么必定不会减其他因子,因为减之后就是会给肯定能赢
的情况了,那么就减2^(k-1),谁减到2谁就输了,因为2不能再减了。
*/
int t, n;
int main()
{
scanf("%d", &t);
while (t--)
{
scanf("%d", &n);
int m = n, cnt = 0;
while (m % 2 == 0)
{
m /= 2;
cnt++;
}
if (m == 1) //为1 才看下面情况 因为他不为1就不是2^k形式
if (cnt == 0 || (cnt % 2 == 1)) //1 2 8 32 128 ....情况
printf("czq\n");
else //4 16 64 256 ....情况
printf("fcx\n");
else if (n % 2) //否则看奇偶
printf("czq\n");
else
printf("fcx\n");
}
}
四、小蜗的爱好(签到)
就是记录a的个数然后用剩余的数量和a的数量进行比较,如果a大就是n,如果a小就是2*a-1;
#include <stdio.h>
#include<string.h>
int main()
{
char s[51];
int i,c1, c2 = 0;
scanf("%s", s);
c1 =strlen(s);//strlen()函数返回字符串长度
for (i = 0; i < c1; i++)
{
if (s[i] == 'a')
{
c2++;
}
}
if (c2 > c1 / 2)// a字符的个数严格大于长度的一半的情况
{
printf("%d\n", c1);
}
else
{
printf("%d\n", 2 * c2 - 1);
}
return 0;
}
五、海绵宝宝的驾校考试(中等)
前缀和和差分的题。
#include <stdio.h>
const int N = 1e6 + 5;
int a[N], b[N];
int min(int a, int b) //找两个数里面最小的
{
if (a < b)
return a;
else
return b;
}
int main()
{
int n, p;
scanf("%d%d", &n, &p);
for (int i = 1; i <= n; i++)
{
scanf("%d", &a[i]);
}
b[0] = a[0];
for (int i = 1; i <= n; i++)
b[i] = a[i] - a[i - 1]; //建立差分数组
while (p--)
{
int l, r, c;
scanf("%d%d%d", &l, &r, &c);
b[l] += c, b[r + 1] -= c; //进行差分
}
int minn = 10000;
for (int i = 1; i <= n; i++) //差分后求一边前缀和,得到结果
{
a[i] = a[i - 1] + b[i];
minn = min(minn, a[i]);
}
printf("%d\n", minn);
return 0;
}
六、珊迪的新电脑(困难)
考察的是栈和队列的知识
#include<cstdio>
#include<cstring>
#include<iostream>
#include<stack>
using namespace std;
string order;//命令
string p;//当前网站
stack<string>front, back;//front前向堆栈,back后向堆栈
int main()
{
p = "http://www.acm.org/";
while (cin >> order)
{
if (order == "QUIT")//读到指令QUIT时退出浏览器
break;
if (order == "BACK")
{
if (back.empty())
{
cout << "Ignored" << endl;;//由于忽略命令,输出Ignored
continue;//如果向后堆栈为空,则忽略该命令
}
front.push(p);//将当前页面推到前向堆栈的顶部
p = back.top();//从向后堆栈的顶部弹出页面,使其成为新的当前页面
back.pop();//由于后堆栈弹出,因此要出栈
}
else if (order == "FORWARD")
{
if (front.empty())
{
cout << "Ignored" << endl;//由于忽略命令,输出Ignored
continue; //如果前向堆栈为空,则忽略该命令
}
back.push(p);//将当前页面推到向后堆栈的顶部
p = front.top();//从前向堆栈的顶部弹出页面,使其成为新的当前页面
front.pop();//同上
}
else if (order == "VISIT")
{
back.push(p);//将当前页面推到向后堆栈的顶部
cin >> p; //使指定的网页成为新的当前页面
while (!front.empty())front.pop();//前向堆栈被清空
}
cout << p << endl;//打印当前页面的网址
}
return 0;
}
七、学学抓水母(签到)
简单的模拟,每加一个值,然后判断是否小于零就行,小于的话就变成等于零
#include<iostream>
#include<cstring>
#include<queue>
#include<map>
#include<algorithm>
#define ll long long
using namespace std;
int t,n,m,a[200005];
int main(){
scanf("%d",&n);
long long sum=0;
for(int i=1;i<=n;i++) {
scanf("%d",&a[i]);
sum+=a[i];
if(sum<0) sum=0;
}
printf("%lld",sum);
return 0;
}
八、三人的斗争(签到)
//签到题 比较巧妙的就是直接按字符串形式输出 省去了约分的过程 一一枚举答案就行 如果想约分 那就需要计算分子分母的最大公约数gcd
#include<stdio.h>
#include<algorithm>
using namespace std;
int main() {
int n,m;
scanf("%d %d",&n,&m);
int s=max(n,m);
int ans=7-s; //因为题目说是大于等于都算赢 从7减就算上了等于那种情况
if(ans==1) printf("1/6\n");
else if(ans==2) printf("1/3\n");
else if(ans==3) printf("1/3\n");
else if(ans==4) printf("2/3\n");
else if(ans==5) printf("5/6\n");
else if(ans==6) printf("1/1\n");
return 0;
}
九、痞老板和凯伦的秘密计划(中等)
打印图形题,重在找规律,规律其实题目已经明说了,就是代码表示可能不是很顺利
#include<stdio.h>
int i[55][55];
int main()
{
int n;
scanf("%d",&n);
int x=1,y=1;
int sum=1;
while(sum<=n*n)//左上矩阵
{
while(y>0&&sum<=n*n)
{
i[y][x]=sum;
sum+=2;
x++;y--;//第一次如果没有越界就向右上走
}
y++;//越界就下移一位
while(x>0&&sum<=n*n)
{
i[y][x]=sum;
sum+=2;
x--;y++;//第二次向左下走
}
x++;//如果越界就右移一位
}
x=n,y=n,sum=2;
while(sum<=n*n)//右下和左上一样的思路
{
while(y<=n&&sum<=n*n)
{
i[y][x]=sum;
sum+=2;
x--;y++;
}
y--;
while(x<=n&&sum<=n*n)
{
i[y][x]=sum;
sum+=2;
x++;y--;
}
x--;
}
for(int a=1;a<=n;a++)
{
for(int b=1;b<=n;b++)
{
if(b<n)//注意行末没有空格,特判一下
printf("%d ",i[a][b]);
else
printf("%d",i[a][b]);
}
printf("\n");
}//最后打印出来
return 0;
}
十、精明的蟹老板(中等)
模拟题其实这题完全没必要很多的if语句,把幻方扩展开来,
题目的意思就是从第一行中点开始,把每一个下面的数
放到“右上角”,若右上角有数,则放到正下方。
详情请看图(忽略图的粗略程度)
十一、可恶的幽灵船长(防AK)
题目大意:
给一组数,数量为n,每个数有颜色 ‘B’ / ‘R’ , 若是’B’ 则可以对它的值减一,‘R’ 加一
问是否可以构造出一个序列 即一组数里包含 1 到 n ;
思路:
用蓝色的数字去构造前面的数,红色构造后面的数
比如 蓝色有k kk个数 则用蓝色构造 1 到 k 1 到 k1到k,红色构造k + 1 到 n k+1 到 nk+1到n
因为 蓝色都是减值 故 如果它不在这个构造范围内通过减可以进入这个范围 ,红色同理;
这样我们把蓝色和红色分开存储排序,蓝色从小到大,红色从大到小
然后考虑蓝色组 第 i 个数要大于等于i 否则无法构造;
红色组 第i个数要小于等于 n 否则无法构造;
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
const int N=2e5+10;
int t;
int n,bl,rl;
int a[N];
char p[N];
int b[N],r[N];
bool d[N];
bool cmp(int a,int b)
{
return a>b;
}
int main()
{
scanf("%d",&t);
while(t--)
{
bl=rl=0;
memset(d,false,sizeof d);
scanf("%d",&n);
for(int i=0; i<n; i++)
scanf("%d",&a[i]);
scanf("%s",p);
for(int i=0; i<n; i++)
{
if(p[i]=='B')
b[bl++]=a[i];
else
r[rl++]=a[i];
}
sort(b,b+bl);
sort(r,r+rl,cmp);
int res=1;
bool flag=false;
for(int i=0; i<bl; i++)
{
if(b[i]<res)
{
flag=true;
break;
}
d[res++]=true;
}
if(flag)
{
cout<<"NO"<<endl;
continue;
}
res=n;
for(int i=0; i<rl; i++)
{
if(r[i]>res)
{
flag=true;
break;
}
d[res--]=true;
}
if(flag)
{
cout<<"NO"<<endl;
continue;
}
cout<<"YES"<<endl;
}
return 0;
}
十二、蟹堡王的故事(中等)
贪心贪心找策略 动态规划找状态和状态转移方程 本题的贪心策略为以扣分为降序排列,先写扣分多的,如果扣分一样先写截止日期早的,对于一项作业我们当然希望它是在 最晚的时间来写(离截止日期越进越好),这样可以空出前面的时间来写其他作业,所以从最晚的截止日期开始往前推找没有被分配作业的那天,如果找不到那这份作业是完不成了 ,这是就要扣分了。
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef unsigned long long ULL;
const double eps=1e-5;
const double pi=acos(-1.0);
const int mod=1e9+7;
const int INF=0x3f3f3f3f;
const int N=1e3+10;
struct asd{
int d;
int t;
};
asd q[N];
bool vis[N];
bool cmp(asd x,asd y)
{
if(x.t>y.t)
return 1;
else if(x.t==y.t){
if(x.d<y.d)
return 1;
}
return 0;
}
int main()
{
int t;
cin>>t;
while(t--)
{
int n,i,sum,j;
cin>>n;
for(i=1;i<=n;i++){
scanf("%d",&q[i].d);
}
for(i=1;i<=n;i++){
scanf("%d",&q[i].t);
}
sort(q+1,q+n+1,cmp);
memset(vis,0,sizeof(vis));
sum=0;
for(i=1;i<=n;i++){
for(j=q[i].d;j>=1;j--){
if(!vis[j]){
vis[j]=1;
break;
}
}
if(j==0)
sum+=q[i].t;
}
cout<<sum<<endl;
}
return 0;
}
总结
这次大家打的还行,四道没打到的同学要加油了,下场女生和男生都还会再收的,大家加油