我是个c++选手,python就国赛前学了半个下午加晚上,省赛前学了半天。所以填空题部分还是选择了,用c++编程,机房提供了DEV还是很不错的
写题顺序大概是:A,B,C,D,E,F,H,I,j,G。两个多小时的时候已经写完了除了D题和G题的其他题目,然后之后就是在debug,调试python代码了(调试python的remove和pop函数,心得见G题)。对python语法的不熟练应该是比赛的最大的障碍了,临时摸鱼抱佛脚还是不太靠谱的。
print(200/8)
# 答案是25
#include
#include
#include
#include
using namespace std;
typedef long long ll;
int a[] = {2,3,5,7};
bool check(int x)
{
for(int i=2;i*i<=x;i++)
if(x%i==0)
return false;
while(x)
{
int t=x%10;
x/=10;
int flag = 0;
for(int i=0;i<4;i++)
if(a[i]==t)
{
flag=1;
break;
}
if(flag==0) return false;
}
return true;
}
int main()
{
int cnt=0;
for(int i=2;i<=20210605;i++)
if(check(i)) cnt++;
cout<<cnt<<endl;
return 0;
}
答案为1903
#include
#include
#include
#include
#include
using namespace std;
typedef long long ll;
int month[]={0,31,28,31,30,31,30,31,31,30,31,30,31};
int check(int x)
{
int res=0;
while(x)
{
res=res+x%10;
x/=10;
}
return res;
}
int main()
{
int cnt=0;
for(int i=2001;i<=2021;i++)
{
if((i%4==0 && i%100!=0) || i%400==0)
month[2]=29;
else
month[2]=28;
for(int j=1;j<=12;j++)
{
for(int k=1;k<=month[j];k++)
{
int tmp=check(i)+check(j)+check(k);
int a=sqrt(tmp);
if(a*a==tmp)
cnt++;
}
}
}
cout<<cnt<<endl;
return 0;
}
答案为977
(这题乱想了好多假算法)我一开始看错题了,以为是最大权值,算了个答案长度为600多的数字。后面回过头来一想一道10分的填空题用C++写岂不是还要写个高精度,应该不会这么复杂。后面转身一读题,是最小权值,又继承了上面最大权值的假算法接着想了个假算法(类似于一颗哈夫曼树,右边子树高度为1010,左子树每个子树配一个叶子,额,假算法、好坑啊!!!),以上显然错误,这样只可能找出最大的权值。。。后面一想,这个应该是一条链,只带左子树的链或者是一个完全二叉树,时间不够了。赛后发现这题正解应该是dp
s = input()
print(s.upper())
数据范围挺大的所以要以o(n)的复杂度,或者是o(nlogn)跑出来就行,我写了个o(nlogn)的复杂度满足即可
import bisect
import math
N = int(math.sqrt(2*1e12))+5000
f = [i*(i+1)//2 for i in range(N)]
s = [0 for i in range(N)]
for i in range(1,N):
s[i]=s[i-1]+f[i]
def get(x):
if x<1:
return 0
p = bisect.bisect_right(f,x,1,N)
p = p-1
if f[p]==x:
return s[p]
else:
a = x-f[p]
a = a*(a+1)//2
return s[p]+a
t = int(input())
for i in range(t):
l,r = list(map(int,input().split()))
print(get(r)-get(l-1))
数据范围不大,c++用set重载一下,或者map应该就可以过了,大致思路就是模拟,用hash维持一个各个体积的冰山出现的次数和,然后每次询问更新这个维护的容器即可。可惜我用的是python,对map操作不是很熟练,写了个大模拟。。。
记录坑点:这道题比较要注意坑的地方就是,用python的pop或者是remove函数,如果用for循环pop掉或者remove掉之后,之后元素的序号会替换掉之前的元素序号,而遍历仍然在进行,所以遍历的时候会出现报错。我的解决办法是将要remove掉的下标放一个数组里头,然后重点是:放数组里头后remove/pop操作要从后往前remove/pop这样就可以保持修改后的下标不会对之前造成影响。
n,m,k = list(map(int,input().split()))
a = list(map(int,input().split()))
b = []
c = []
mod = 998244353
ans = sum(a)%mod
def calc():
res = 0
res = sum(a)
for i in range(len(b)):
res = res+b[i]*c[i]
res = res%mod
return res
def check(x,y):
q = []
lb = len(b)
for i in range(lb):
if b[i]+x<=0:
q.append(i)
elif b[i]+x>k:
b.append(1)
c.append((b[i]+x-k)*c[i])
b[i] = k
else:
b[i]=b[i]+x
for i in range(len(q)-1,-1,-1):
b.pop(q[i])
c.pop(q[i])
q = []
for i in range(len(a)):
if a[i]+x<=0:
q.append(i)
elif a[i]+x>k:
b.append(1)
c.append(a[i]+x-k)
a[i] = k
else:
a[i] = a[i]+x
for i in range(len(q)-1,-1,-1):
a.pop(q[i])
a.append(y)
for i in range(m):
x,y = list(map(int,input().split()))
check(x,y)
ans = calc()
print(ans)
考场上为了追求速度写了个大暴力,用前缀和和前缀积维护答案,然后两重for循环超级大暴力,应该可以拿50%的分,正解应该是找到数的某种性质
n = int(input())
N = 200010
a = list(map(int,input().split()))
b = [0 for i in range(N)]
s = [1 for i in range(N)]
for i in range(1,n+1):
b[i] = b[i-1]+a[i-1]
s[i] = s[i-1]*a[i-1]
ans = 0
for i in range(1,n+1):
for j in range(i+1,n+1):
if s[j]==s[i-1]*(b[j]-b[i-1]):
ans=ans+1
ans = ans+n
print(ans)
这道题应该是一道数位DP的题,前两周上课设的时候摸鱼打了个比赛,碰到了一个原题,当时写了个爆搜,当然是超时了,之后也没有补题,爆搜是会超时的所以又写了个大暴力
n,k = list(map(int,input().split()))
ans = 0
for i in range(1,n+1):
s = format(i,'b')
if s.count('1')==k:
ans+=1
print(ans)
写的真暴力,要是补题了这个原题应该可以秒掉吧
这道题正解在考场上没出来,就用栈模拟了一下其中的过程,得分大概是60%或者是40%
n,m = list(map(int,input().split()))
a = input()
s = [a[i] for i in range(len(a))]
def turn(l,r):
for i in range(l,r+1):
if s[i]=='(':
s[i]=')'
elif s[i]==')':
s[i]='('
def check(p):
q = []
res = 0
for i in range(p,n):
if s[i]=='(':
q.append('(')
elif s[i]==')':
if len(q)==0:
return res
elif len(q)==1:
res = i+1
q.pop(0)
elif len(q)>1:
q.pop(0)
return res
for i in range(m):
x = list(input().split())
if x[0]=='1':
turn(int(x[1]),int(x[2]))
elif x[0]=='2':
ans = check(int(x[1])-1)
print(ans)