1.日期统计
分析:100个数字可以存在一个静态数组中,对于统计的日期,另外再用一个数组存储。而不知道具体数组的大小,就没办法初始化,所以使用一个动态数组存储,比如STL库中的set容器,因为题目要求相同的日期只需要统计一次,set容器的特点就是可以避免相同的键值,使用这个容器的优势还在于方便的进行数据的插入和长度的计算,可以很好的用来解题。再者它是一个八位日期的数字,前四位相同,所以只需要存储后四位数字即可,利用八重循环,找出合法日期。注意在月份和天数处理时,判断其合法性,由于2023不能被4整除也不能被100整除,所以是平年。2月只有28天,以月份作为天数的判断条件。对于月份或者天数的长度只有一位时,题目要求补充前导零。可以这么来处理,把它当作一个四位数来看。月份的前导零可以不用添加,当月份只有一位数时乘以100直接加上天数,这样天数只有一位时,前导零便有了。
源代码:
#include <bits/stdc++.h>
using namespace std;
int num[110];
int days[13] = { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
int main() {
for (int i=0;i<100;i++) cin >>num[i]; //输入100个数
set<int> ans;
for (int i = 0; i < 100; i++)
for (int j = i + 1; j < 100; j++)
for (int k = j + 1; k < 100; k++)
for (int v = k + 1; v < 100; v++) //前4个数字构成年
{
int y = num[i] * 1000 + num[j] * 100 + num[k] * 10 + num[v]; //年
if (y == 2023) { //找到了年,再找月、日
for (int m = v + 1; m < 100; m++)
for (int n = m + 1; n < 100; n++)
for (int o = n + 1; o < 100; o++)
for (int p = o + 1; p < 100; p++)
{
int mon = num[m] * 10 + num[n]; //月
int d = num[o] * 10 + num[p]; //日
if ((mon >= 1 && mon <= 12) && (d >= 1 && d <= days[mon]))
{
int temp = mon * 100 + d;
ans.insert(temp); //用set去重
}
}
break;
}
}
cout << ans.size();
return 0;
}
2.01串的熵
分析:这个题目也是纯暴力,可以通过枚举解题。假如有x个1,那么就有23333333-x个0,直接根据公式计算信息熵,写一个函数,因为c++有log2()函数,所以可以直接拿来用。把计算出来的信息熵与题目给的数字求差的绝对值,精度精确到1e-4方即可。因为题目要求0的次数比1少,所以对于输出的两个数中,取较小的数。
源代码:
#include<bits/stdc++.h>
using namespace std;
double hs(int a,int b){
double x1=1.0*a/(a+b);
double x2=1.0*b/(a+b);
double ans=-a*x1*log2(x1)-b*x2*log2(x2);
return ans;
}
int main(){
for(int i=0;i<=23333333;i++){
if(fabs(hs(i,23333333-i)-11625907.5798)<0.0001){
cout<<i<<endl;
break;
}
}
return 0;
}
3.冶炼金属
分析:75/3=25 53/2=26 59/2=29 Vmax取最小 75/(3+1)=18 53/(2+1)=17 59/(2+1)=19 Vmin等于最大值加1,因为边界取不到,所以最小值取最大数加1.
源代码:
#include <bits/stdc++.h>
using namespace std;
int main()
{
int Vmax=999999999,Vmin=0,n;
cin>>n;
for(int i=1;i<=n;i++){
int x1,x2;
cin>>x1>>x2;
int t1=x1/(x2+1)+1;
if(t1>Vmin)
Vmin=t1;//更新最小值
int t2=x1/x2;
if(t2<Vmax)
Vmax=t2;//更新最小值
}
cout<<Vmin<<" "<<Vmax;
return 0;
}
4.飞机降落
分析:对于该题可以采用dfs算法,当前飞机的状态,开始降落的时间T加上盘旋的的时间D要大于等于上一架飞机的最早降落时间time,否则飞机相撞。反之可以降落,更新飞机的最早降落时间max(T,time)+L,全部降落成功则输出YES,在降落过程中可能有多种方案,只要有一种状态成功即可,这里可以剪枝。反之只要有一架飞机不能成功降落,则需要进行回溯,穷举所有情况,如果都不能成功降落,则输出NO。
#include<bits/stdc++.h>
using namespace std;
const int Max_N=11;
bool have_answer,use[Max_N];//use[Max_N]表示尝试降落的飞机
int T,N,t[Max_N],d[Max_N],l[Max_N];
void dfs(int x,int time){
if(have_answer)return;
if(x==N){//全部降落成功
have_answer=1;
return;
}
for(int i=1;i<=N;i++){
if(!use[i]&&time<=t[i]+d[i]){//降落时间比最晚时间要早,就可以尝试去降落
use[i]=1;
dfs(x+1,max(t[i],time)+l[i]);//更新降落时间
if(have_answer)return;
use[i]=0;
}
}
}
int main(){
cin>>T;
while(T--){
cin>>N;
have_answer=0;
for(int i=1;i<=N;i++){
cin>>t[i]>>d[i]>>l[i];
use[i]=0;
}
dfs(0,0);
if(have_answer)cout<<"YES\n";
else cout<<"NO\n";
}
return 0;
}
5.接龙序列
分析:求最少的删除个数,也就是求解出数列中最长的接龙数列,计算出最长的接龙数列长度,数列总长度-最长接龙数列长度等于最少删除次数。可以尝试用动态规划来解,状态为当前最长接龙数列长度,则dp[i]就是以i为数字最后一位的最长接龙数列长度,设x为当前数字的第一位(如果为接龙数列,也就是前一位数的最后一位),y为当前数字的最后一位,则状态转移方程可以写为dp[y]=max(d[x]+1,dp[y])。
源代码:
#include <bits/stdc++.h>
using namespace std;
int dp[10];//必须声明为全局变量
int main()
{
int N;
cin>>N;
string s;
int m=0;
for(int i=0;i<N;i++){
cin>>s;
int x=s[0]-'0',y=s[s.size()-1]-'0';
dp[y]=max(dp[x]+1,dp[y]);//状态转移方程
m=max(m,dp[y]);
}
cout<<N-m<<endl;
return 0;
}
6.岛屿个数
#include<bits/stdc++.h>
using namespace std;
const int MAX_N=51;
int M,N;
string mp[MAX_N];
bool vis[MAX_N][MAX_N],used[MAX_N][MAX_N];
//八个方向 下 上 右 左 右下 左下 右上 左上
int dx[]={0,0,1,-1,1,-1,1,-1};
int dy[]={1,-1,0,0,1,1,-1,-1};
bool bfs_out(int x,int y){
//为避免走重复的路 需要新建一个数组来标记走的路 每次使用都要清空
for(int i=0;i<M;i++){
for(int j=0;j<N;j++)
used[i][j]=0;
}
queue<int>qx,qy;
qx.push(x);qy.push(y);used[x][y]=1;
while(!qx.empty()){
x=qx.front();qx.pop();
y=qy.front();qy.pop();
//如果走到边界 那么它就是一个单独的岛屿
if(x==0||x==M-1||y==0||y==N-1) return true;
for(int i=0;i<8;i++){
int nx=x+dx[i];
int ny=y+dy[i];
//如果岛屿出界 或者路线已经走过了 或者是陆地 那么就不要
if(nx<0||ny<0||nx>=M||ny>=N||used[nx][ny]||mp[nx][ny]=='1')continue;
//把该路线连接起来
qx.push(nx);qy.push(ny);
used[nx][ny]=1;
}
}
//没逃出去
return false;
}
void bfs_col(int x,int y){
queue<int>qx,qy;
//标记岛屿
qx.push(x);qy.push(y);vis[x][y]=1;
while(!qx.empty()){
x=qx.front();qx.pop();
y=qy.front();qy.pop();
for(int i=0;i<4;i++){
int nx=x+dx[i];
int ny=y+dy[i];
//如果岛屿出界 或者被访问过 或者是海水 那么就不要
if(nx<0||ny<0||nx>=M||ny>=N||vis[nx][ny]||mp[nx][ny]=='0')continue;
//把该岛屿连接起来
qx.push(nx);qy.push(ny);
vis[nx][ny]=1;
}
}
}
void solve(){
cin>>M>>N;
for(int i=0;i<M;i++){
cin>>mp[i];
for(int j=0;j<N;j++)
vis[i][j]=0;
}
int ans=0;
for(int i=0;i<M;++i)
for(int j=0;j<N;j++)
//如果这个点没被标记过并且是一个岛屿
if(!vis[i][j]&&mp[i][j]=='1'){
//那么进行染色
bfs_col(i,j);
//判断岛屿能否逃出去 可以 就计入岛屿总数中 反之 不能逃出去 那就是子岛屿 不用管
if(bfs_out(i,j))++ans;
}
cout<<ans<<'\n';
}
int main(){
ios::sync_with_stdio(0);cin.tie(0);
int T;cin>>T;
while(T--) solve();
return 0;
}
分析:题目核心在于 判断一个岛屿是不是子岛屿,取决于这个岛屿是否被围住了。如果这个岛屿能够“逃到”地图的边界,那么它就不是一个子岛屿,就是一个单独的岛屿,需要统计。岛屿出现时,标记相邻的岛屿(上,下,左,右),表示同属于一个岛屿,检查某个岛屿能否从边界逃出去,去走海水,如果能连接到边界的海水,那么它就不是一个子岛屿,就需要统计,注意逃的时候,是上,下,左,右,左上,左下,右上,右下八个方向。
7.子串简写
分析:可以利用前缀和的思想,先收集所有以c1开头的字符,每一次收集时,判断相隔k-1个字符的结尾字符是否以c2结尾,如果是,那么将之前遇到的c1全部累加,可以想象成一个滑条,从最开始的c1滑到当前符合条件的c2,循环一轮即得出结果。
#include <bits/stdc++.h>
using namespace std;
int k;
char c1,c2;
string s;
int main()
{
cin>>k>>s>>c1>>c2;
long long ans=0;
int q_z_h=0;
//保持字串的第一个字符与最后一个字符的长度至少为k
for(int j=k-1,i=0;i<s.size();i++,j++){
//出现以c1开始的子串 找到符合条件的c1并累加
if(s[i]==c1) q_z_h++;
//出现以c2结束的子串 如果符合条件 那么将之前的c1都累加求和 最后得出结果
if(s[j]==c2) ans+=q_z_h;
}
cout<<ans;
return 0;
}
8.整数删除
#include <bits/stdc++.h>
using namespace std;
map<int,int>p;
bool comp(const pair<int,int>left,const pair<int,int>right){
return left.second<right.second;
}
int main()
{
ios::sync_with_stdio(0),cin.tie(0);
int N,K;
cin>>N>>K;
for(int i=0;i<N;i++){
cin>>p[i];//以i为键 键盘读入的数为值
}
//定义迭代器指针
map<int,int>::iterator it;
while(K--){//开始删除
//在it容器中找到second成员最小的pair<int, int>元素,并将指向该元素的迭代器存储在it(迭代器)中。
//把it想象成一个引用变量 从p中取值
it=min_element(p.begin(),p.end(),comp);
int A=it->second;//获取最小值
if(it!=p.begin()){//it不是第一个值
it--;
//it为迭代器 存储两个数值 不能直接与int A相加
it->second+=A;
it++;
}
if(it!=p.end()){//it不是最后一个值
it++;
it->second+=A;
it--;
}
//删除最小值
p.erase(it);
}
for(it=p.begin();it!=p.end();it++)
cout<<it->second<<" ";
return 0;
}
30%通过
#include<bits/stdc++.h>
using namespace std;
#define val first
#define pos second
typedef long long LL;
typedef pair<LL,int>PLI;
const int MAX_N=5e5+5;
int N,K,pre[MAX_N],nxt[MAX_N];
LL A[MAX_N];
priority_queue<PLI>q;
int main(){
ios::sync_with_stdio(0);cin.tie(0);
cin>>N>>K;
for(int i=1;i<=N;i++){
cin>>A[i];
pre[i]=i-1;
nxt[i]=i+1;
q.push({-A[i],-i});
}
pre[1]=-1;
nxt[N]=-1;
while(K--){
PLI now;
do{
now=q.top();q.pop();
now.val=-now.val;now.pos=-now.pos;
}while(A[now.pos]!=now.val);
int PRE=pre[now.pos];
int NXT=nxt[now.pos];
if(PRE!=-1){
A[PRE]+=now.val;
q.push({-A[PRE],-PRE});
nxt[PRE]=NXT;
}
if(NXT!=-1){
A[NXT]+=now.val;
q.push({-A[NXT],-NXT});
pre[NXT]=PRE;
}
A[now.pos]=-1;
}
for(int i=1;i<=N;++i)
if(A[i]!=-1)
cout<<A[i]<<' ';
return 0;
}
9.景区导游
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int MAX_N=1e5+1;
vector<int>E[MAX_N],W[MAX_N];
int N,K,dep[MAX_N],fa[MAX_N][21],A[MAX_N];
LL dis[MAX_N];
void dfs(int u,int Fa){
dep[u]=dep[Fa]+1;
fa[u][0]=Fa;
for(int i=1;i<=20;++i)
fa[u][i]=fa[fa[u][i-1]][i-1];
for(int i=0;i<E[u].size();++i){
int v=E[u][i],w=W[u][i];
if(v==Fa) continue;
dis[v]=dis[u]+w;
dfs(v,u);
}
}
int LCA(int u,int v){
if(dep[u]<dep[v]) swap(u,v);
for(int i=20;i>=0;--i)
if(dep[fa[u][i]]>=dep[v])
u=fa[u][i];
if(u==v) return u;
for(int i=20;i>=0;--i)
if(fa[u][i]!=fa[v][i]){
u=fa[u][i];
v=fa[v][i];
}
return fa[u][0];
}
LL path_dis(int u,int v){
if(!u || !v) return 0;
return dis[u]+dis[v]-2*dis[LCA(u,v)];
}
int main(){
ios::sync_with_stdio(0); cin.tie(0);
cin>>N>>K;
for(int i=1;i<N;++i){
int u,v,t; cin>>u>>v>>t;
E[u].push_back(v);
W[u].push_back(t);
E[v].push_back(u);
W[v].push_back(t);
}
dfs(1,0);
LL ans=0;
for(int i=1;i<=K;++i){
cin>>A[i];
ans+=path_dis(A[i],A[i-1]);
}
for(int i=1;i<=K;++i)
cout<<ans-path_dis(A[i-1],A[i])-path_dis(A[i],A[i+1])+path_dis(A[i-1],A[i+1])<<' ';
return 0;
}
10.砍树
#include "bits/stdc++.h"
using namespace std;
using ll = long long;
int main()
{
ios::sync_with_stdio(false);
cin.tie(0),cout.tie(0);
int n,m;
cin >> n >> m;
vector<vector<pair<int,int>>> edge(n + 1);
for(int i = 1;i < n;i ++) {
int x,y;
cin >> x >> y;
edge[x].push_back({y,i});
edge[y].push_back({x,i});
}
vector<vector<int>> f(n + 1,vector<int>(19,0));
vector<int> dep(n + 1),d(n + 1);
function<void(int,int)> dfs = [&](int x,int fa) {
f[x][0] = fa;
dep[x] = dep[fa] + 1;
for(int i = 1;i <= 18;i ++) {
f[x][i] = f[f[x][i - 1]][i - 1];
}
for(auto [v,id]: edge[x]) {
if(v != fa) {
dfs(v,x);
}
}
};
auto LCA = [&](int x,int y) -> int {
if(dep[x] < dep[y]) swap(x,y);
int d = dep[x] - dep[y];
for(int i = 18;i >= 0;i --) {
if(d >> i & 1) x = f[x][i];
}
if(x == y) return x;
for(int i = 18;i >= 0;i --) {
if(f[x][i] != f[y][i]) {
x = f[x][i];
y = f[y][i];
}
}
return f[x][0];
};
int ans = -1;
function<void(int,int)> get = [&](int u,int fa) {
for(auto [v,id]: edge[u]) {
if(v != fa) {
get(v,u);
d[u] += d[v];
}
}
for(auto [v,id]: edge[u]) {
if(d[u] == m && d[v] == m) {
ans = max(ans,id);
}
}
};
dfs(1,0);
for(int i = 1;i <= m;i ++) {
int x,y;
cin >> x >> y;
int lca = LCA(x,y);
d[x] ++,d[y] ++;
d[lca] --,d[f[lca][0]] --;
}
get(1,0);
cout << ans;
return 0;
}