题目链接:http://acm.zju.edu.cn/onlinejudge/showContestProblems.do?contestId=392
上周六是浙江省赛,总结一下做出来的水题
因为太菜所以别的题都不会
G:
题目大意:
第一行是n,然后给n个数
找出大于等于它并且能被7整除且不能被4整除的数。
水题所以直接暴力:
#include <iostream>
#include <cstdio>
using namespace std;
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
int n;
scanf("%d",&n);
int i=n;
for(;;i++)
if(i%7==0)
break;
for(;;i+=7)
if(i%4)
{
printf("%d\n",i);
break;
}
}
return 0;
}
F:
题目大意:
第一行给个n,然后n行字符串
把每个字符串中的元音字母去掉(第一个字母除外)
水题直接写就行,需要注意一点元音包括y
代码:
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
char str[105];
scanf("%s",str);
printf("%c",str[0]);
for(int i=1;i<strlen(str);i++)
if(str[i]!='a'&&str[i]!='e'&&str[i]!='i'&&str[i]!='o'&&str[i]!='u'&&str[i]!='y')
printf("%c",str[i]);
printf("\n");
}
return 0;
}
I:
题目大意:
第一行一个n,然后n行,每行一个a,b
问斐波那契数列从第a项加到第b项的和是奇数还是偶数。
观察斐波那契数列可以发现它是奇奇偶奇奇偶…
所以任意连续三个数相加肯定是偶数(奇+奇+偶=偶)
所以只需看一下从a开始的(b-a+1)%3个数加起来是奇数还是偶数就行了
因为之后的加起来肯定是一个偶数
看数据规模挺大的所以写了个python
第一次交python,感觉还行
代码:
t=int(raw_input())
for i in range(0,t):
a,b=map(int,raw_input().split())
c=(b-a+1)%3
if c==0 :
print(0)
elif c==1 :
if a%3==0 :
print(0)
else:
print(1)
else :
if (a%3!=0 and (a+1)%3!=0) or (a%3==0 and (a+1)%3==0):
print(0)
else:
print(1)
输入的时候要用raw_input(),否则oj会报奇怪的错误
后来磊磊说可以直接判断a和b能否被3整除就行,所以可以直接用c++写
H:
题目大意:
t组样例,每组给出n个数。
如果一个数比它左右两个都大,那么就把它当做一个“凸起”
在这n个数中最多可以删掉一个,问“凸起”最少是多少个
最初想到先标记一下哪些数是凸起,然后再依次删掉所有凸起元素,看哪种删法凸起最少
然后发现凸起最少的删法不一定是把凸起删掉。并且这个数据规模复杂度最多就是O(n)。
因为删一个数最多只能影响他自己和他左右两个数,所以可以在标记完了之后用O(n)的时间检查一下把第i个数删掉之后对它自己,它左边,它右边这三个数有什么影响。
注意一下边界条件就行。
代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
#define LL long long
#define N 100005
#define CL(a,b) memset(a,b,sizeof(a))
using namespace std;
/*sum:第一遍遍历,统计凸起个数。del:删除第i个元素,看看比原来少了几个凸起。
最好的情况是少了两个,比如1 3 2 3 1把2删掉。
a[N]:原始数组。mark[N]:标记是否为凸起。
*/
int n,sum,del;
int a[N],mark[N];
//判断下标index的元素是否是凸起。第一个最后一个肯定不是凸起,所以先特判一下
int check1(int index)
{
if(index<=0||index>=n-1)
return 0;
if(a[index]>a[index-1]&&a[index]>a[index+1])
return 1;
return 0;
}
//判断index左边(或右边)元素删除后它还是不是凸起。isleft=1时index的左边被删除
//index=0时右边被删除。
int check2(int index,int isleft)
{
if(index<=0||index>=n-1)
return 0;
if(isleft==1&&index==1)
return 0;
if(isleft==0&&index==n-2)
return 0;
if(isleft&&a[index]>a[index-2]&&a[index]>a[index+1])
return 1;
if(!isleft&&a[index]>a[index-1]&&a[index]>a[index+2])
return 1;
return 0;
}
//统计一下index被删除后凸起数量变化情况
int cal(int index)
{
if(index>0&&index<n-1)
return mark[index]+mark[index-1]+mark[index+1]-check2(index-1,0)-check2(index+1,1);
if(index==0)
return mark[index]+mark[index+1]-check2(index+1,1);
if(index==n-1)
return mark[index]+mark[index-1]-check2(index-1,0);
return 0;
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
scanf("%d",&n);
CL(a,0);
CL(mark,0);
sum=del=0;
for(int i=0;i<n;i++)
scanf("%d",&a[i]);
for(int i=0;i<n;i++)
{
mark[i]=check1(i);
sum+=mark[i];
}
for(int i=0;i<n;i++)
{
del=max(del,cal(i));
if(del==-2)
break;
}
printf("%d\n",sum-del);
}
return 0;
}
E:
题目大意:
t组样例,每组n个数。
对这n个数进行调整:每次可以将其中任意一个数放到最左边,问最少调整几次之后这n个数是一个递增的数列。
找规律
经过暴力模拟、单调栈等失败的尝试,总算找到
几个规律:
1.每个元素最多只会被调整一次,当然也可能不会被调整到。
2.特判:如果输入序列已经为递增序列那么直接输出0就行。
3.特判:如果输入序列的最大值是第一个元素,那么其余n-1个元素都需要调整。所以直接输出n-1。
4.由上一条可以想到,当最大值在中间时,最大值右边的元素都要被调整。
5.如果一个数,它左边有比它大的,那么它应该被调整。
综上,可以建立一个leftmax数组,记录前i个元素中的最大值。
其中leftmax[0]=a[0],leftmax[i]=max(leftmax[i-1],a[i])。如果a[i]<leftmax[i-1],那么a[i]会被调整。
然后声明一个变量delmax,记录一定会被调整的元素中的最大值。
如果a[i]<leftmax[i-1] || a[i]<delmax,则a[i]会被调整。
代码如下:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define LL long long
#define N 100005
#define CL(a,b) memset(a,b,sizeof(a))
using namespace std;
int a[N],leftmax[N];
int n,maxindex,maxx,delmax;
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
scanf("%d",&n);
CL(a,0);
CL(leftmax,0);
maxindex=delmax=maxx=-1;
int flag=0;
for(int i=0;i<n;i++)
{
scanf("%d",&a[i]);
if(maxx<=a[i])
{
maxx=a[i];
maxindex=i;
}
if(i&&a[i]<a[i-1])
flag=1;
}
if(!flag)
{
printf("0\n");
continue;
}
if(maxindex==0)
{
printf("%d\n",n-1);
continue;
}
else
{
leftmax[0]=a[0];
for(int i=1;i<maxindex;i++)
{
if(a[i]<leftmax[i-1])
delmax=max(a[i],delmax);
leftmax[i]=max(leftmax[i-1],a[i]);
}
for(int i=maxindex+1;i<n;i++)
delmax=max(delmax,a[i]);
int sum=n-1-maxindex;
for(int i=0;i<maxindex;i++)
if(a[i]<leftmax[i]||(a[i]<delmax&&delmax!=-1))
sum++;
printf("%d\n",sum);
}
}
return 0;
}
加一个找到的大佬写的解题报告(小菜鸡瑟瑟发抖)
https://blog.csdn.net/LSD20164388/article/details/89606289