1 特殊日期
2000.1.1~2000000.1.1有几天满足: 年是月和日的倍数
答案:35813063
n31=[1,3,5,7,8,10,12]
count=0
for n in range(2000,2000000):
flag=0
if (n%4==0 and n%100!=0) or n%400==0:
flag=1
for y in range(1,13):
max = 30
if y in n31:
max=31
if y==2:
max=28
if flag==1:
max=29
for r in range(1,max+1):
if n%y==0 and n%r==0:
count+=1
count+=1
print(count)
2 分糖果
两种糖果分别有9个和16个,要全部分给7个小朋友,每个小朋友得到的糖果总数最少为2个最多为5个,问有多少种不同的分法。糖果必须全部分完。
只要有其中一个小朋友在两种方案中分到的糖果不完全相同,这两种方案就算作不同的方案。答案:5067671
class a():
sum=0
def dfs(self,n, ta, tb):
# 如果最后一个小朋友分到的糖在范围内,则sum加一
if n==7:
if ta+tb>=2 and ta+tb<=5:
self.sum+=1
return
# 两种糖的所有组合形式
for i in range(ta+1):
for j in range(tb+1):
if i+j>=2 and i+j<=5:
self.dfs(n+1,ta-i,tb-j)
if __name__ == '__main__':
a=a()
a.dfs(1, 9, 16)
print(a.sum)
3 三国游戏
n=int(input())
a=list(map(int,input().split('')))
b=list(map(int,input().split(' ')))
c=list(map(int,input().split(' ')))
class aa():
max=0
def dfs(self,x,y,z,i,shi):
# 所有事件都发生/不发生完毕
if i==n+1 and (x+y<z or x+z<y or y+z<x):
# print(x,y,z)
self.max=max(self.max,shi)
return
# print(a,b,c)
if i<=n:
# 如果发生
self.dfs(x+a[i-1],y+b[i-1],z+c[i-1],i+1,shi+1)
# 如果不发生
self.dfs(x,y,z,i+1,shi)
aa=aa()
# print(a,b,c)
aa.dfs(0,0,0,1,0)
if aa.max==0:
print(-1)
else:
print(aa.max)
4 平均
思路:
- 将每个数字的代价放入cost[i]中
- 统计每个数字的个数放入num
- 如果该数字的个数num大于n/10,则找其代价最小的num-n/10个数字的代价加起来
n=int(input())
cost=[[] for i in range(10)]
num=[0]*10
for i in range(n):
a,b=map(int,input().split())
cost[a-1].append(b)
# 统计每个数字的个数
num[a-1]+=1
q=0
for i in range(10):
if num[i]>n/10:
# 升序
cost[i].sort(reverse=False)
# print(newcost)
for m in range(int(num[i]-n/10)):
q+=cost[i][m]
# 如果该数字的个数num大于n/10,则找其代价最小的num-n/10个数字的cost加起来
print(q)
5 翻转
思路:
- 先比较首位和尾位,不一样则无法变为相同输出-1
- 从第二位到倒数第二位依次比较,如果不同则查看S的前一位和后一位是否相同且与本位不同,满足则可翻转修改,不满足则无法修改输出-1
def a(n,S,T,count,i):
if S[i][0]!=T[i][0] or S[i][len(S[i])-1]!=T[i][len(S[i])-1]:
return -1
for j in range(1,len(S[i])-1):
if S[i][j]!=T[i][j]:
if S[i][j-1]==S[i][j+1] and S[i][j-1]!=S[i][j]:
count+=1
S[i][j]=T[i][j]
continue
return -1
return count
n=int(input())
S=[0 for i in range(n)]
T=[0 for i in range(n)]
for i in range(n):
T[i]=list(input())
S[i]=list(input())
count=0
for i in range(n):
print(a(n,S,T,count,i))
6 子矩阵
第一版:(40%通过,其余超时,思路为每次都比较矩阵中所有值)
n,m,a,b=map(int,input().split())
z=[[] for i in range(n)]
sum=0
for i in range(n):
z[i]=list(map(int,input().split()))
#纵向遍历range(n-a+1)
#横着遍历range(m-b+1)
for i in range(n-a+1):
for j in range(m-b+1):
zong=[float('inf'),float('-inf')]
for t in range(a):
for r in range(b):
zong[0]=min(z[i+t][j+r],zong[0])
zong[1]=max(z[i+t][j+r],zong[1])
sum+=zong[0]*zong[1]
print(sum%998244353)
第二版:50%,思路为计算每行滑动窗口的最大值最小值
n,m,a,b=map(int,input().split())
z=[[] for i in range(n)]
sum=0
for i in range(n):
z[i]=list(map(int,input().split()))
#纵向遍历range(n-a+1)
#横着遍历range(m-b+1)
zong=[[[float('inf'),float('-inf')]for i in range (m-b+1)]for j in range(n)]
for j in range(m-b+1):
for i in range(n):
for r in range(b):
zong[i][j][0]=min(z[i][j+r],zong[i][j][0])
zong[i][j][1]=max(z[i][j+r],zong[i][j][1])
if i>=a-1:
maxe=float('-inf')
mine=float('inf')
for t in range(a):
mine=min(zong[i-t][j][0],mine)
maxe=max(zong[i-t][j][1],maxe)
sum+=mine*maxe
print(sum%998244353)
7 阶乘的和
超时
n=int(input())
A=list(map(int,input().split()))
sum=0
for i in range(len(A)):
aaa=1
for j in range(2,A[i]+1):
aaa*=j
sum+=aaa
jie=1
maxe=float('-inf')
for j in range(1,sum):
jie*=j
if sum%jie==0:
maxe=max(maxe,j)
if jie*(j+1)>sum:
break
print(maxe)
8 奇怪的数
思路1:超时
import sys
sys.setrecursionlimit(100000) # 例如这里设置为十万
class eee():
n, m = map(int, input().split())
ma = 0
def next(self,count, maxe, er, san, si):
for o in range(count % 2, maxe + 1, 2):
if count == self.n - 5 + 1:
self.ma += 1
continue
elif self.m - er - san - si - o >= 0:
self.next(count + 1, self.m - er - san - si - o, san, si, o)
return
eee = eee()
count = 1
for yi in range(1, 10, 2):
for er in range(0, 10, 2):
for san in range(1, 10, 2):
for si in range(0, 10, 2):
maxe = eee.m - yi - er - san - si
if maxe >= 0:
s = eee.next(count, maxe, er, san, si)
print(eee.ma%9982443)
9 子树的大小
import math
T=int(input())
count=[0]*T
for i in range(T):
n,m,k=map(int,input().split())
row=math.ceil(math.log(((m-1)*k+1),m))
sumrow=math.ceil(math.log(((m-1)*n+1),m))
#计算节点k的子树从该节点开始到sumrow-1层的总节点数
count1=(1-m**(sumrow-row))/(1-m)
#计算第row行k节点前面的节点占它的百分之多少,用这个比例乘以第sumrow行总节点数得出节点k的子树在第sumrow行从第几开始
nqian=m**(sumrow-1)*(k-((1-m**row)/(1-m)-m**(row-1)+1))/m**(row-1)
#如果sumrow行有该子树节点,则加上
if n-((1-m**sumrow)/(1-m)-m**(sumrow-1)+1)-nqian>=0:
count1+=min(n-((1-m**sumrow)/(1-m)-m**(sumrow-1)+1)-nqian+1,m**(sumrow-row))
count[i]=count1
for i in range(T):
print(int(count[i]))
10 反串或01串
-
反异或=翻转rev+异或(反异或<=一次)
-
0添加在左侧或右侧(无限用)
-
1添加在左侧或右侧(min)
s=list(map(int,input()))
n=len(s)
d=[[0]*n for i in range(n)]
#单个字符为对称子串
for i in range(n):
d[i][i]=1
#和下一个字符相等为对称字串
for i in range(n-1):
if s[i]==s[i+1]:
d[i][i+1]=1
#长度为3—n的子串
for j in range(3,n+1):
#从0—n-(j-1)开始的子串
for i in range(n-(j-1)):
#如果首尾相等且除了首位的子串为对称的则它对称
if s[i]==s[i+j-1] and d[i+1][i+j-2]==1:
d[i][i+j-1]=1
#最大对称子串中1的个数
c=0
#最大对称子串的首位下标
f=[0,0]
#从第一个字符开始遍历
for i in range(n):
#找到该字符开始的最长子串(倒着来快)
for j in range(n-1,i,-1):
#如果是对称字串(首尾为1+长度为偶数或长度为奇数且中间为0)
if d[i][j]==1 and s[i]==1 and ((j-i)%2!=0 or ((j-i)%2==0 and s[i+int((j-i)/2)]==0)):
count=0
for k in range(i,j+1):
if s[k]==1:
count+=1
if count>c:
#print(count)
c=count
f=[i,j]
l=0
if f[0]==f[1] and f[0]==0:
for i in range(n):
if s[i]==1:
l+=1
else:
#对称串中的1除以二为异或翻转前1的个数
l=c/2
#遍历对称串前的串
for i in range(f[0]):
if s[i]==1:
l+=1
#遍历对称串后的串
for i in range(f[1]+1,n):
if s[i]==1:
l+=1
print(int(l))