2024.4.7 【南天寂静亮星少,北落师门赛明灯。】
Sunday 二月三十
<theme = oi-“search”>
A. 填充单词
题目描述
小C认识很多单词,但是他并不喜欢其中的一些单词。具体地说,如果一个单词包含连续的3个元音字母,或连续的3个辅音字母,或者1个“L”字母都不包含的话,这个单词是不被小C喜欢的。其中元音字母仅为A、E、I、O、U这5个字母,剩下的字母全部为辅音字母。
现在给你一个部分残缺的单词,问一共有多少种方法用26个字母来填满这个单词,使得小C是喜欢这个单词的?
格式
输入格式
输入仅一行包括 1 个长度不超过100 的全部由字符串,表示残缺的单词,其中残缺的部分用’_’ 表示。
输出格式
输出仅一行,包括1 个正整数,表示不同的方案数。这个数字可能会很大,请用long long存储。
Samples
输入数据 1
L_V
输出数据 1
5
输入数据 2
V__K
输出数据 2
10
输入数据 3
JA_BU_K_A
输出数据 3
485
数据范围与提示
10组测试数据下划线的个数为3,5,6,7,9,10,10,10,10,10
搜索做法
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
string s;
ll ans;int cnt,tl;
char w[30]={'A','E','I','O','U','y','f'};
bool yuan(char d){
for(int i=0;i<6;++i){
if(d==w[i])return 1;
}
return 0;
}
ll ksm(ll a,ll b){
ll num=1;
while(b>0){
if(b&1)num=num*a;
a=a*a;
b>>=1;
}
return num;
}
void dfs(int p,int y,int ty,int t_y){
if(p>int(s.size())-1){
if(tl==1){
ans+=ksm(5,t_y)*ksm(21,cnt-t_y);
}
else ans+=ksm(5,t_y)*(ksm(21,cnt-t_y)-ksm(20,cnt-t_y));
return;
}
if(yuan(s[p])){
ty=max(1,ty);
if(y==p-1&&y!=0){
++ty;
if(ty==3)return;
}
y=p;
}
else{
ty=0;
}
if(p-y>=3)return;
if(s[p+1]=='_'){
s[p+1]='y';
dfs(p+1,y,ty,t_y+1);
s[p+1]='f';
dfs(p+1,y,ty,t_y);
s[p+1]='_';
}
else dfs(p+1,y,ty,t_y);
return;
}
int main(){
ios::sync_with_stdio(false);
cin.tie(nullptr);
//freopen("A.in","r",stdin);
//freopen(".out","w",stdout);
cin>>s;
s='0'+s;
for(int i=1;i<=int(s.size())-1;++i){
if(s[i]=='_')++cnt;
if(s[i]=='L')tl=1;
}
dfs(0,0,0,0);
cout<<ans<<endl;
return 0;
}
DP做法
#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int maxn = 110;
ll dp[maxn][5][2];
char s[maxn];
int main(){
cin>>s;
int n = strlen(s);
for(int i = n;i > 0;i--){
s[i] = s[i-1];
}
if(s[1] == '_'){
dp[1][1][0] = 0,dp[1][2][0] = 0,dp[1][3][0] = 5,dp[1][4][0] = 20;
dp[1][1][1] = 0,dp[1][2][1] = 0,dp[1][3][1] = 0,dp[1][4][1] = 1;
}
else if(s[1] == 'A'||s[1] == 'E'||s[1] == 'I'||s[1] == 'O'||s[1] == 'U'){
dp[1][1][0] = 0,dp[1][2][0] = 0,dp[1][3][0] = 1,dp[1][4][0] = 0;
dp[1][1][1] = 0,dp[1][2][1] = 0,dp[1][3][1] = 0,dp[1][4][1] = 0;
}
else if(s[1] == 'L'){
dp[1][1][0] = 0,dp[1][2][0] = 0,dp[1][3][0] = 0,dp[1][4][0] = 0;
dp[1][1][1] = 0,dp[1][2][1] = 0,dp[1][3][1] = 0,dp[1][4][1] = 1;
}
else{
dp[1][1][0] = 0,dp[1][2][0] = 0,dp[1][3][0] = 0,dp[1][4][0] = 1;
dp[1][1][1] = 0,dp[1][2][1] = 0,dp[1][3][1] = 0,dp[1][4][1] = 0;
}
for(int i = 2;i <= n;i++){
if(s[i] != '_'){
if(s[i] == 'A'||s[i] == 'E'||s[i] == 'I'||s[i] == 'O'||s[i] == 'U'){
dp[i][1][0] = dp[i-1][3][0];
dp[i][2][0] = 0;
dp[i][3][0] = dp[i-1][2][0]+dp[i-1][4][0];
dp[i][4][0] = 0;
dp[i][1][1] = dp[i-1][3][1];
dp[i][2][1] = 0;
dp[i][3][1] = dp[i-1][2][1]+dp[i-1][4][1];
dp[i][4][1] = 0;
}
else{
if(s[i] == 'L'){
dp[i][1][0] = 0;
dp[i][2][0] = 0;
dp[i][3][0] = 0;
dp[i][4][0] = 0;
dp[i][1][1] = 0;
dp[i][2][1] = dp[i-1][4][1]+dp[i-1][4][0];
dp[i][3][1] = 0;
dp[i][4][1] = dp[i-1][1][1]+dp[i-1][1][0]+dp[i-1][3][0]+dp[i-1][3][1];
}
else{
dp[i][1][0] = 0;
dp[i][2][0] = dp[i-1][4][0];
dp[i][3][0] = 0;
dp[i][4][0] = dp[i-1][1][0]+dp[i-1][3][0];
dp[i][1][1] = 0;
dp[i][2][1] = dp[i-1][4][1];
dp[i][3][1] = 0;
dp[i][4][1] = dp[i-1][1][1]+dp[i-1][3][1];
}
}
}
else{//j: 1 2y 2 2f 3 y 4 f
dp[i][1][0] = dp[i-1][3][0]*5;
dp[i][2][0] = dp[i-1][4][0]*20;
dp[i][3][0] = dp[i-1][2][0]*5+dp[i-1][4][0]*5;
dp[i][4][0] = dp[i-1][1][0]*20+dp[i-1][3][0]*20;
dp[i][1][1] = dp[i-1][3][1]*5;
dp[i][2][1] = dp[i-1][4][1]*21+dp[i-1][4][0];
dp[i][3][1] = dp[i-1][2][1]*5+dp[i-1][4][1]*5;
dp[i][4][1] = dp[i-1][1][1]*21+dp[i-1][3][1]*21+dp[i-1][1][0]+dp[i-1][3][0];
}
}
/*
for(int i = 1;i <= n;i++){
for(int j = 1;j <= 4;j++){
cout<<dp[i][j][0]<<"|"<<dp[i][j][1]<<" ";
}
cout<<endl;
}
*/
cout<<dp[n][1][1]+dp[n][2][1]+dp[n][3][1]+dp[n][4][1];
}
B. 解方程
题目描述
考虑以下的方程形式:
a
∗
x
1
2
+
b
∗
x
2
2
+
c
∗
x
3
2
+
d
∗
x
4
2
=
0
a * x^2_1+b * x^2_2+c * x^2_3+d * x^2_4 = 0
a∗x12+b∗x22+c∗x32+d∗x42=0
a,b,c,d是区间[-50,50]内的整数。
求满足以下条件的方程解
(
x
1
,
x
2
,
x
3
,
x
4
)
(x_1,x_2,x_3,x_4)
(x1,x2,x3,x4)
的个数:x是区间[-100,100]内的非零整数。
格式
输入格式
单组输入数据,输入四个整数,表示a,b,c,d
输出格式
输出一个整数,表示解的个数。
Samples
输入数据 1
1 2 3 -4
输出数据 1
39088
输入数据 2
1 1 1 1
输出数据 2
0
数据范围与提示
对于5%的数据,a,b,c,d均为 0;
对于另外10%的数据,a,b,c,d中有 3 个 0 ;
对于另外25%的数据,a,b,c,d中有 2 个 0 ;
对于另外30%的数据,a,b,c,d中有 1个 0 ;
对于剩余30%的数据,无特殊限制 ;
#include<bits/stdc++.h>
using namespace std;
int main()
{
int a,b,c,d;
long long count = 0;
cin >> a >> b >> c >> d;
for(int x1 = 1;x1 <= 100;x1++)
for(int x2 = 1;x2 <= 100;x2++)
for(int x3 = 1;x3 <= 100;x3++)
for(int x4 = 1;x4 <= 100;x4++)
if(a * x1 * x1 + b * x2 * x2 + c * x3 * x3 + d * x4 * x4 == 0) count++;
cout << count * 16 << endl;
return 0;
}
不需要过多思考,直接暴力啊。
C. AB数字游戏
题目描述
小C和小T又在玩数字游戏了。这次的规则是这样的:最开始有两个空的数列 A 和 B,第 i 次小T会给数列 A 和 B 分别加上一个数
A
i
,
B
i
A_i,B_i
Ai,Bi,而小C可以将 A 和 B 以任意方式重新排序,使得
A
i
+
B
i
A_i+B_i
Ai+Bi 的最大值最小。
请你帮小C在每一次小T给出两个新的数之后,求出最大值的最小值。
格式
输入格式
第一行包括 1 个正整数 N,表示小T给出数字的次数。
接下来 N 行,第 i+1 行包括 2 个正整数 A i , B i A_i,B_i Ai,Bi,表示每次一小T给出的数对。
输出格式
输出包括 N 行,对于每一次小T 给出的数字,求出所求排列中对应 A 和 B 之和的最大值的最小值。
样例
输入数据 1
3
2 8
3 1
1 4
输出数据 1
10
10
9
输入数据 2
3
1 1
2 2
3 3
输出数据 2
2
3
4
数据范围与提示
对于 50%的数据,有 N≤200,
对于 100%的数据,有 1≤N≤100000,1≤A,B≤100。
第一组样例解释:
第一次询问:A = {2}, B = {8},MIN{Ai + Bi}=2+8=10;
第二次询问:A = {2,3}, B = {8,1},MIN{Ai + Bi}=2+8=10;
第三次询问:A = {1,2,3}, B = {8,1,4},MIN{Ai + Bi}=1+8=9;
//Zn
#include<bits/stdc++.h>
#include<bits/extc++.h>
using namespace std;
using namespace __gnu_pbds;
int n,ta,tb,ans,l,r,tot,t;
int a[110],b[110];
int c[110],d[110];
int main()
{
ios::sync_with_stdio(0);
cin>>n;
for(int i=1;i<=n;i++)
{
cin>>ta>>tb;
a[ta]++;
b[tb]++;
ans=0;
for(int i=1;i<=100;i++)
c[i]=a[i];
for(int j=1;j<=100;j++)
d[j]=b[j];
l=1;
r=100;
tot=0;
while(tot<i*2)
{
while((!c[l])&&l<100) l++;
while((!d[r])&&r>1) r--;
t=min(c[l],d[r]);
ans=max(ans,l+r);
tot+=t*2;
c[l]-=t;
d[r]-=t;
}
cout<<ans<<'\n';
}
return 0;
}
D. 可交换数字最大连续和
题目描述
一个长度为n 数组 A 的最大连续和,是指所有满足
1
≤
L
≤
R
≤
n
1≤L≤R≤n
1≤L≤R≤n 的 a[i]和的最大值。一次交换操作是指:(1) 选择两个下标 i 和(i∗j)(2) 进行赋值,$tmp=A[i],A[i]=A[j],A[j]=tmp $;
给定一个长度为 n 的数组, 最多进行 m 次交换操作后,该数组的最大连续和。
输入格式
第一行两个两个整数 n和m。
第二行n 个数字,表示数组中的元素。
输出格式
输出答案。
样例
输入数据 1
10 2
10 -1 2 2 2 2 2 2 -1 10
输出数据 1
32
输入数据 2
5 10
-1 -1 -1 -1 -1
输出数据 2
-1
第四题没人解出来。。。。