A.小锋的书
问一个字符串中有没有连续的七个及以上的”1”或”0”,只需要定义两个变量记录连续最大的”1”和”0”的数量即可。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
char st[1000];
int main() {
scanf("%s",st);
int zero=0,one=0,maz=0,mao=0;
//这里有四个变量,zero和one记录遍历过程中,连续的1和0的数量
//maz和mao则记录连续的0串和1串最大长度
for(int i=0;i<strlen(st);i++){ //遍历字符串
if(st[i]=='1'){
one++; //如果是1,”1”串长度++
if(one>mao)mao=one; //同时如果大于最大长度,更新mao
zero=0; //遇到1的话说明0串中断了,zero 归零
}else {
zero++; //这一部分和上面同理
if(zero>maz)maz=zero;
one=0;
}
}
if(mao>=7||maz>=7)printf("YES");//简单的输出
else printf("NO");
return 0;
}
B.大海我来了
根据每个人所属的类别先后输出不同类的人名,可以按照题目要求的顺序,进行四次循环判断。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
struct po//定义结构体存储每个人的名字和类别
{
char name[19],rank[19];
}per[109];
int vis[109];/*定义一个记录输出情况的数组,在这里仅用这个数组判断哪个是未输出的船长。*/
/*我们也可以利用这个数组实现一种可能更简单的方法,在读入时将这四类人记为1,2,3,4,然后分别存入数组,之后每次判断输出时只需要用这个数组进行判断即可。*/
int main() {
int n;
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%s %s",per[i].name,per[i].rank);
}
for(int i=1;i<=n;i++){
if(!strcmp(per[i].rank,"rat")){
/*这里使用的是strcmp()函数,不懂使用方法可百度*/
vis[i]=1; //这个数组把已经输出的第i个人记为1,而其他未输出为0
printf("%s\n",per[i].name);
}
}
for(int i=1;i<=n;i++){
if(!strcmp(per[i].rank,"child")||!strcmp(per[i].rank,"woman")){
vis[i]=1;
printf("%s\n",per[i].name);
}
}
for(int i=1;i<=n;i++){
if(!strcmp(per[i].rank,"man")){
vis[i]=1;
printf("%s\n",per[i].name);
}
}
for(int i=1;i<=n;i++){
if(!vis[i]){ //最后1个仍未输出的即是船长
printf("%s\n",per[i].name);
break;
}
}
return 0;
}
C.拔河比赛
这道题很简单,只需要判断三个方向上的合力是否都为零,如果都为0,则受力平衡。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
int main() {
int n,x=0,y=0,z=0,a,b,c;//x,y,z要赋值为0
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%d%d%d",&a,&b,&c);
x+=a,y+=b,z+=c; //累加
}
if(!x&&!y&&!z)printf("YES\n");//简单的判断三个方向的合力是否都为0
else printf("NO\n");
return 0;
}
D.子序列和
枚举子序列计算总和的方式显然不现实,考虑枚举每位a[i]最总和造成的贡献。
假设包含a[i]的子序列共有k个,那么a[i]的贡献值便为a[i]*k;
假设对于当前子序列,a[i]已经选了,那么其他所有元素都有选和不选两种情况,最后包含的a[i]的子序列便有个,n为序列总长度。
举例如 ,求包含 的子序列共有多少个,那么 选不选会分出来两种情况为 和 , 选不选又分出来更多的情况,为, 同理,所以除了 以外其他元素要考虑n-1次,最后包含ai的子序列共有 个。
另一方面,计算 次方本题中可以在算每一位的贡献之前预处理出来,即开个for循环n次用一个数组,存 的值,或者可以直接用快速幂计算,不了解快速幂的可以学一下。
此处为了照顾大多数人就不用快速幂了。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
const int MOD=1e9+7,maxn=1e6+5;
int n,a[1000005];
long long BS[1000005];
void init()
{
BS[0]=1;
for(int i=1;i<=maxn-1;i++)
{
BS[i]=(BS[i-1]%MOD*2)%MOD;
}
}
int main()
{
init();
scanf("%d",&n);
long long res=0;
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
res=res%MOD+(a[i]%MOD*BS[n-1]%MOD)%MOD;
}
printf("%lld\n",res);
return 0;
}
E.博学的学长
典型签到题,直接输出。 当然,你也可以去查ASCII码表。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
int main() {
printf("%c%c%c%c%c%c%c",67,72,70,89,89,68,83);
return 0;
}
F.人生的抉择
题目看似复杂,其实原理很简单,用BA,BC向量的叉乘就可判断。 BAxBC(叉乘)=|BA|*|BC|*sinθ ,θ为两向量的夹角。(注意叉乘的顺序如果调换,判断原则也要变换)叉乘的计算为两向量交叉相乘再相减。
夹角为90°时,向右转,叉乘的乘积大于0;
夹角为180°时,直走,叉乘乘积为0;
夹角为270°时,向左转,乘积小于0。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
int main() {
long long xa,ya,xb,yb,xc,yc; //三个点,记得用long long
scanf("%lld%lld%lld%lld%lld%lld",&xa,&ya,&xb,&yb,&xc,&yc);
long long ans=(xa-xb)*(yc-yb)-(xc-xb)*(ya-yb);
if(ans==0)printf("TOWARDS");
else if(ans<0)printf("LEFT");
else printf("RIGHT");
return 0;
}
G.小锋卖瓜
简单的贪心思想
三种情况:
1.已经有了顾客需求种类的瓜,直接下一个;
2.没有顾客需要的瓜,容器还没有满,直接去进货,路费+1;
3.没有顾客需要的瓜且容器已满,这是需要扔掉某种瓜,这里就要用到贪心的思想,需要 扔掉最晚用到的一种瓜,才能使总的路费最少。
#include <stdio.h>
int a[100],have[100],vis[100][100],rem[100],num[100];
int main()
{
int n,k,sum=0,total=0;
scanf("%d%d",&n,&k);
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
vis[a[i]][rem[a[i]]]=i;//保存每种瓜出现的天数
rem[a[i]]++;
//rem记录每种瓜已经出现几天,保证vis数组能按顺序存储a[i]种瓜都在哪一天出现
}
for(int i=1;i<=n;i++){
vis[i][rem[i]]=0x3f3f3f3f;//将每种瓜的最后一位置为最大值
}
for(int i=1;i<=n;i++){
num[a[i]]++; //记录当前循环a[i]种瓜已经出现几次
if(have[a[i]])continue;//have记录容器中已有的瓜,1为有
else if(total<k){ //第二种情况,直接去进货
total++; //容器已用空间+1
have[a[i]]=1;
}else{
int ma=-1,flag;
for(int j=1;j<=n;j++){
if(have[j]&&vis[j][num[j]]>ma){
//如果容器中有这种瓜,并且这种瓜出现的下一个天数大于当前最大值
//因为上面已经将每种瓜的最后一位置为最大数,即后面已经不需要该种瓜,可以丢弃
ma=vis[j][num[j]],flag=j;//更新最大值,记录瓜的种类
}
}
have[a[i]]=1,have[flag]=0;//丢弃瓜,买新瓜
}
sum++;//sum只在需要买瓜的时候+1
}
printf("%d",sum);
return 0;
}
H.对称括号序列
考虑由符合题意得k对括号序列的构成方式:
以代表由k对括号可以构成的合法对称括号序列的数量;
根据规则2,由k-1对括号序列在外侧增加一个括号,形如为 ( P ) ,其数量为 个;
根据规则3,由k-2对括号序列分别在左侧和右侧增加一个括号,形如 ( ) P ( ) ,其数量为 个;
综上,得到递推方程: ;
但是形如 (())(()) 之类的括号序列虽然是对称的,但是不能由题目给出的规则构造得到,所以不计入答案数量中,最后注意取模即可。
同时,这道题的结论也是斐波那契数列,直接手推前几项找规律也可以,前提是要读懂构造规则~~(读不懂建议remake)~~。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
const int MOD=1e9+7;
int t,n;
long long F[1000005];
int main()
{
scanf("%d",&t);
F[1]=1,F[2]=2;
for(int i=3;i<=1000004;i++) F[i]=(F[i-1]%MOD+F[i-2]%MOD)%MOD;
while(t--){
scanf("%d",&n);
printf("%lld\n",F[n]);
}
return 0;
}
ps:特别鸣谢杨哲聚聚的大力支持。