试题 算法训练 Sereja and Squares
提交此题
资源限制
时间限制:4.0s 内存限制:256.0MB
问题描述
Sereja在平面上画了n个点,点i在坐标(i,0)。然后,Sereja给每个点标上了一个小写或大写英文字母。Sereja不喜欢字母"x",所以他不用它标记点。Sereja认为这些点是漂亮的,当且仅当:
·所有的点可以被分成若干对,使得每个点恰好属于一一对之中。
·在每对点中,横坐标较小的会被标上小写字母,较大的会被标上对应的大写字母。
·如果我们在每对点上画一个正方形,其中已知的一对点会作为正方形的相对的顶点,它们间的线段会成为正方形的对角线,那么在所有画出的正方形中不会有相交或触碰的情况。
小Petya擦掉了一些小写字母和所有大写字母,现在Sereja想知道有多少种方法来还原每个点上的字母,使得还原后这些点是漂亮的。
输入格式
第一行是一个整数n,表示点的个数。
第二行是一个长度为n的字符串,包含小写字母和问号"?",是按照横坐标递增的顺序的每个点的描述。问号表示这个点的字母被Petya擦掉了。保证输入串不含字母"x"。
输出格式
输出答案对4294967296取模的值。如果没有可行的方案,输出0。
样例输入
4
a???
样例输出
50
样例输入
4
abc?
样例输出
0
样例输入
6
abc???
样例输出
1
数据规模和约定
20个测试点的n分别为:
5,10,20,50,100,
200,500,1000,2000,5000,
10000,20000,30000,40000,50000,
60000,70000,80000,90000,100000.
n=int(input())
s=list(input())
dp=[[0for i in range(n)] for j in range(2)]
m=0
n2=n//2
now=0
dp[0][0]=1
for i in range(n):
if s[i]=='?':
now^=1
for j in range((i+1)//2+1):
#print(now,j)
dp[now][j]=dp[now^1][j]+dp[now^1][j-1]
#print(dp[now])
else:
m+=1
if (n2<m or n%2!=0):
print(0)
else :
for i in range(n2-m):
dp[now][n2]*=25
dp[now][n2]=dp[now][n2]%4294967296
print(dp[now][n2])
n=int(input())
s=list(input())
#dp=[[0]*n for i in range(n)]
f=[0]*n
f[0]=1
m=0
n2=n//2 #n>>1
#print (n2)
for i in range(n):
if s[i]=='?':
j=(i+1)//2 #(i+1)>>1
while j>=1:#max(1,(i+1)-n2)
f[j]+=f[j-1]
j-=1
print(f)
else:
m+=1
print(f)
if (n2<m or n%2!=0):
print(0)
else:
i=n2-m
while i>0:
f[n2]*=25
f[n2]= f[n2]%4294967296
i-=1
print(f[n2])
思路
我们dp里面储存的是前i个字符串里面存在j个大的字母的情况有几种,最后再乘25就好了。
- 一个细节是乘的时候我们乘的是不确定选啥字母的才乘也就是n2-m个
- i+1的时候假如加上的是一个?,那么dp[i+1][j]=dp[i][j]+dp[i][j-1]即之前的j个大字母的情况(?是小字母)+之前j-1个大字母的情况(?是大字母)。