合法密码
问题描述
小蓝正在开发自己的 OJ 网站。他要求网站用户的密码必须符合以下条件:
- 长度大于等于 88 个字符,小于等于 1616 个字符。
- 必须包含至少 11 个数字字符和至少 11 个符号字符。
例如 **lanqiao2024!
、+-*/0601
、8((>w<))8**
都是合法的密码。 而 **12345678
、##\*\*##\*\*
、abc0!#
、lanqiao20240601!?**
都不是合法的密码。
请你计算以下的字符串中,有多少个子串可以当作合法密码?只要两个子串的开头字符和末尾字符在原串中的位置不同,就算作不同的子串。
字符串为:
kfdhtshmrw4nxg#f44ehlbn33ccto#mwfn2waebry#3qd1ubwyhcyuavuajb#vyecsycuzsmwp31ipzah#catatja3kaqbcss2th
code:
遍历一遍。
#include<bits/stdc++.h>
using namespace std;
int ans=0;//400
string s="kfdhtshmrw4nxg#f44ehlbn33ccto#mwfn2waebry#3qd1ubwyhcyuavuajb#vyecsycuzsmwp31ipzah#catatja3kaqbcss2th";
bool solve(string str)
{
int f1=0,f2=0;
for(int i=0;i<str.size();i++)
{
if(str[i]>='0'&&str[i]<='9') f1=1;
else if(str[i]>='a'&&str[i]<='z'||str[i]>='A'&&str[i]<='Z') continue;
else f2=1;
}
if(f1&&f2) return true;
else return false;
}
int main()
{
for(int i=0;i<s.size()-16;i++)
{
int j;
for(j=8;j<=16;j++)
{
string ss=s.substr(i,j);
if(solve(ss))
{
ans=ans+16-j+1;
break;
}
}
}
cout<<ans;
return 0;
}
选数概率
code
转化得公式。
#include<bits/stdc++.h>
using namespace std;
int main()
{
int s1=517*5;
int s2=2632;
int s3=308*5;
int p=__gcd(s1*s3,__gcd(s2*s1,s2*s3));
cout<<s1*s3/p<<','<<s1*s2/p<<','<<s2*s3/p;//55,94,56
return 0;
}
蚂蚁开会
问题描述
二维平面上有 nn 只蚂蚁,每只蚂蚁有一条线段作为活动范围,第 ii 只蚂蚁的活动范围的两个端点为 (uix,uiy),(vix,viy)(uix,uiy),(vix,viy)。现在蚂蚁们考虑在这些线段的交点处设置会议中心。为了尽可能节省经费,它们决定只在所有交点为整点的地方设置会议中心,请问需要设置多少个会议中心?
输入格式
输入共 n+1n+1 行。第一行为一个正整数 nn。后面 nn 行,每行 44 个由空格分开的整数表示 uix,uiy,vix,viyuix,uiy,vix,viy。
输出格式
输出共 11 行,一个整数表示答案。
样例输入
4
0 0 4 4
0 4 4 0
2 0 0 4
2 1 2 3
样例输出
2
样例说明
所有线段之间共有 33 个不同的交点:(0,4),(4,3),(2,2)(0,4),(4,3),(2,2),其中整点有 22 个:(0,4),(2,2)(0,4),(2,2)。
code
记录所有线段经过的点。
#include<bits/stdc++.h>
using namespace std;
int n;
map<pair<int,int>,int>mp;
int ans=0;
int main()
{
cin>>n;
for(int i=0;i<n;i++)
{
int sx,sy;
int fx,fy;
cin>>sx>>sy>>fx>>fy;
int x=fx-sx;
int y=fy-sy;
int p=abs(__gcd(x,y));
int nx=sx,ny=sy,dx=x/p,dy=y/p;
while(1)
{
mp[{nx,ny}]++;
nx+=dx;
ny+=dy;
if(nx<min(sx,fx)||max(sx,fx)<nx||ny<min(sy,fy)||max(sy,fy)<ny) break;
}
}
for(auto &i:mp)
{
if(i.second>=2)ans++;
}
cout<<ans;
return 0;
}
立定跳远
问题描述
在运动会上,小明从数轴的原点开始向正方向立定跳远。项目设置了 nn 个检查点 a1,a2,...,ana1,a2,...,an 且 ai≥ai−1>0ai≥ai−1>0。小明必须先后跳跃到每个检查点上且只能跳跃到检查点上。同时,小明可以自行再增加 mm 个检查点让自己跳得更轻松。在运动会前,小明制定训练计划让自己单次跳跃的最远距离达到 LL,并且学会一个爆发技能可以在运动会时使用一次,使用时可以在该次跳跃时的最远距离变为 2L2L。小明想知道,LL 的最小值是多少可以完成这个项目?
输入格式
输入共 22 行。第一行为两个正整数 n,mn,m。第二行为 nn 个由空格分开的正整数 a1,a2,...,ana1,a2,...,an。
输出格式
输出共 11 行,一个整数表示答案。
样例输入
5 3
1 3 5 16 21
样例输出
3
样例说明
增加检查点 10,13,1910,13,19,因此每次跳跃距离为 2,2,5,3,3,3,22,2,5,3,3,3,2,在第三次跳跃时使用技能即可。
code:
二分法:逐渐查找到最小得L值,贪心:使用技能相当于多一个检查点。
#include <bits/stdc++.h>
using namespace std;
const int N = 1e5 + 9;
int a[N],n,m;
int check(int x)
{
int cnt = 0;
for(int i=1;i<=n;i++)
{
cnt += (a[i] - a[i-1] - 1) / x + 1 - 1;
}
return cnt <= m + 1;
}
int main()//贪心 使用技能相当于检查点加一
{
cin >> n >> m;
for(int i=1;i<=n;i++) cin >> a[i];
sort(a+1,a+1+n);
int l = 0 , r = 1e8+5;
while(l<r)
{
int mid = l + r >> 1;
if(check(mid)) r = mid;
else l = mid + 1;
}
cout<<l;
return 0;
}
最小字符串
问题描述
给定一个长度为 NN 且只包含小写字母的字符串 SS,和 MM 个小写字母 c1,c2,...,cMc1,c2,...,cM。现在你要把 MM 个小写字母全部插入到字符串 SS 中,每个小写字母都可以插入到任意位置。请问能得到的字典序最小的字符串是什么?
输入格式
第一行包含两个整数 NN 和 MM。第二行包含一个长度为 NN 的字符串 SS。第三行包含 MM 个小写字母 c1,c2,...,cMc1,c2,...,cM。
输出格式
输出一个长度为 N+MN+M 的字符串代表答案。
样例输入 1
4 3
abbc
cba
样例输出 1
aabbbcc
样例输入 2
7 3
lanqiao
bei
样例输出 2
beilanqiao
code
按序输出即可。
#include<bits/stdc++.h>
using namespace std;
int n,m;
string s,s1;
int main()
{
cin>>n>>m;
cin>>s>>s1;
sort(s1.begin(),s1.end());
int i=0,j=0;
while(i<n&&j<m)
{
if(s[i]<=s1[j]) cout<<s[i++];
else cout<<s1[j++];
}
while(i<n) cout<<s[i++];
while(j<m) cout<<s1[j++];
return 0;
}
数位翻转
问题描述
小明创造了一个函数 f(x)f(x) 用来翻转 xx 的二进制的数位(无前导 00)。比如 f(11)=13f(11)=13,因为 11=(1011)211=(1011)2,将其左右翻转后,变为 13=(1101)213=(1101)2;再比如 f(3)=3f(3)=3,f(0)=0f(0)=0,f(2)=f(4)=f(8)=1f(2)=f(4)=f(8)=1 等等。小明随机出了一个长度为 nn 的整数数组 {a1,a2,...,an}{a1,a2,...,an},他想知道,在这个数组中选择最多 mm 个不相交的区间,将这些区间内的数进行二进制数位翻转(将 aiai 变为 f(ai)f(ai))后,整个数组的和最大是多少?
输入格式
输入共 22 行。第一行为两个正整数 n,mn,m。第二行为 nn 个由空格分开的整数 a1,a2,...,ana1,a2,...,an。
输出格式
输出共 11 行,一个整数表示答案。
样例输入 1
5 3
11 12 13 14 15
样例输出 1
67
样例说明 1
只翻转 a1a1,和为 13+12+13+14+15=6713+12+13+14+15=67。
样例输入 2
6 2
23 8 11 19 16 35
样例输出 2
134
样例说明 2
翻转区间 [a3,a4][a3,a4] 和 [a6][a6],和为 23+8+13+25+16+49=13423+8+13+25+16+49=134。
code
dp
#include<bits/stdc++.h>
using namespace std;
#define ll long long
int n,m;
int a[1010];
int d[1010];
ll dp[1010][1010];///dp[i][j] 表示处理前 i 个数,选择了 j 个不相交区间的最大增益和
ll ans=0;
void solve(int val,int num)
{
int x=val;
int y=0;
while(x>0)
{
int now=x%2;
x/=2;
y=y*2+now;
}
d[num]=y-val;
}
int main()
{
cin>>n>>m;
for(int i=1;i<=n;i++)
{
cin>>a[i];
ans+=a[i];
solve(a[i],i);
}
for(int i=1; i<=n; i++)
{
for(int j=1; j<=m; j++) dp[i][j]=max(dp[i][j],dp[i-1][j]);//不选选 复制下来
for(int j=1; j<=m; j++)
{
ll sum=0;
for(int k=i; k>=1; k--)
{
sum+=d[k];
dp[i][j]=max(dp[i][j],dp[k-1][j-1]+sum);//选
}
}
}
cout<<ans+dp[n][m]<<endl;
return 0;
}
跳石头
问题描述
小明正在和朋友们玩跳石头的小游戏,一共有 nn 块石头按 1 到 nn 顺序排成一排,第 ii 块石头上写有正整数权值 cici 。
如果某一时刻小明在第 jj 块石头,那么他可以选择跳向第 j+cjj+cj 块石头 (前提 j+cj≤nj+cj≤n )或者跳向第 2j2j 块石头(前提 2j≤n2j≤n ),没有可跳跃的目标时游戏结束。
假如小明选择从第 xx 块石头开始跳跃,如果某块石头有可能被小明经过 ("经过"指存在某一时刻小明在这个石头处),则将这块石头的权值纳入得分集合 SxSx ,那么小明从第 xx 块石头开始跳跃的得分为 ∣Sx∣∣Sx∣ 。
比如如果小明从第 xx 块石头出发,所有可能经过的石头上的权值分别为 5,3,5,2,35,3,5,2,3 ,那么 Sx=5,3,2Sx=5,3,2 得分为 ∣Sx∣=3∣Sx∣=3 。小明可以任选一块石头开始跳跃,请求出小明最多能获得的分数。
输入格式
输入共 22 行。
第一行为一个正整数 nn。
第二行为 nn 个由空格分开的正整数 c1,c2,…,cnc1,c2,…,cn。
输出格式
输出共 1 行,一个整数表示答案。
样例输入
5
4 3 5 2 1
样例输出
4
code
多次dfs找出最多得解
#include<bits/stdc++.h>
using namespace std;
#define int long long
int n,m;
int c[40010];
int ans=0;
set<int>se;
void dfs(int x)
{
ans=max(ans,(int)se.size());
if(2*x<=n)
{
se.insert(c[2*x]);
dfs(2*x);
}
if(x+c[x]<=n)
{
se.insert(c[x+c[x]]);
dfs(x+c[x]);
}
}
signed main()
{
ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
cin>>n;
for(int i=1;i<=n;i++)
cin>>c[i];
for(int i=1;i<=n;i++)
{
se.clear();
se.insert(c[i]);
dfs(i);
}
cout<<ans;
return 0;
}
最长回文前后缀
code
由题知,只能删一个子串,判断首尾长度后,从左向右/从右向左 各一遍遍历,找到删去子串得最优解。
#include<bits/stdc++.h>
#define int long long
using namespace std;
int solve(string str)
{
string s=str;
int len=0;
int res=-1;
int l=0,r=s.size()-1;
while(l<=r&&s[l]==s[r])
{
l++;
r--;
len++;
}
for(int j=r;j>=l;j--)
{
if(s[j]==s[l])
{
int ll=l,rr=j;
int cnt=0;
while(ll<=rr&&s[rr]==s[ll])
{
ll++;
rr--;
cnt++;
}
res=max(res,cnt);
}
}
return len+res;
}
signed main()
{
std::ios::sync_with_stdio(false);
cin.tie(0) , cout.tie(0);
string s;
cin>>s;
string ss=s;
reverse(ss.begin(),ss.end());
int ans=max(solve(s),solve(ss));
cout<<ans;
return 0;
}