本溪市网站建设_网站建设公司_VS Code_seo优化
2026/1/16 22:43:36 网站建设 项目流程

2026年嘉应学院寒假算法冬令营结训赛

A B2029 大象喝水 - 洛谷

数学题,对于圆周率 π ,可以×100之后再除回去,避免小数带来的精度误差。

void solve(){int h,r;cin>>h>>r;int sum=h*314*r*r;//cout<<sum<<endl;int res=20000*100;if(res%sum)cout<<res/sum+1<<endl;else cout<<res/sum<<endl; 
}

B P1152 欢乐的跳 - 洛谷

模拟题,把两相邻数之差用st数组标记即可。注意相差过大可能会造成越界问题,需要加个判断。

void solve(){cin>>n;for(int i=1;i<=n;i++)cin>>a[i];for(int i=2;i<=n;i++){int tmp=abs(a[i]-a[i-1]);if(tmp<n)st[tmp]=1;}int flag=1;for(int i=1;i<=n-1;i++){if(st[i]==0){cout<<"Not jolly"<<endl;return;}}cout<<"Jolly"<<endl;
}

C P1923 【深基9.例4】求第 k 小的数 - 洛谷

题目标签所提到了分治法, 可以理解为是我们ACWing快速排序的递归分治的策略,时间复杂度O(n logn)

或者洛谷题解中的快速选择算法:
递归查找,先选择一个基数(可以选择最右侧元素/中位数/随机选择),然后反复进行分区,将数组分为小于基准和大于基准两部分。接下来进入递归处理部分:根据 k 和基数的位置关系,决定选左半边还是右半边。如果 k 就是基数呢?直接输出就好了。 O(n)

如果使用sort,因为数据量过大(超过\(10^5\)), 必须加上加速(关闭流同步)

void solve(){cin>>n>>k;for(int i=0;i<n;i++)cin>>a[i];sort(a,a+n);cout<<a[k]<<endl;
}
signed main(){ios::sync_with_stdio(0);cin.tie(0),cout.tie(0);int _=1;//cin>>_;while(_--)solve();return 0;
} 

D P1216 [IOI 1994 / USACO1.5] 数字三角形 Number Triangles - 洛谷

非常经典的一道 线性DP 的题目。
需要从倒数第二层开始,选择它下面两个位置的值。这个值记作从最后一层开始,路径上的最大总和。具体方法可以参考AcWing 898. 数字三角形 - AcWing

void solve(){cin>>n;for(int i=1;i<=n;i++){for(int j=1;j<=i;j++)cin>>g[i][j];}for(int i=n-1;i>=1;i--){for(int j=1;j<=i;j++)g[i][j]+=max(g[i+1][j],g[i+1][j+1]);}cout<<g[1][1]<<endl;
}

E P3799 小 Y 拼木棒 - 洛谷

4根木棒组成一个正三角形,则必有 2根长度相等。
且另外2根长度之和,等于前2根相等的木棒 的长度。
意识到这个就显而易见了(虽然我赛时没想出来T-T)

各木棍长度 \(a_i\)≤5000,我们可以预处理每个长度的选择\(C^{2}_{(cnt_{a_i})}\) ,
再从1到\(a_i\)/2 枚举另外两根长度, 时间复杂度 O(\(n^2\)) 。

void solve(){cin>>n;for(int i=1;i<=n;i++)cin>>a[i],cnt[a[i]]++;int res=0;for(int i=1;i<=5000;i++){int tmp=cnt[i]*(cnt[i]-1)/2%mod;if(tmp==0)continue;//取模要充分,避免超出范围//如果有负数出现,要(sum%mod+mod)%modfor(int j=1;j<i/2;j++){res+=cnt[j]*cnt[i-j]%mod*tmp%mod;res%=mod;}//如果另外两根相等:if(i%2==0){res+=cnt[i/2]*(cnt[i/2]-1)/2%mod*tmp%mod;res%=mod;}else {//别漏了这个,是上面j<i/2的遗漏问题T-Tres+=cnt[i/2]*cnt[i/2+1]%mod*tmp%mod;res%=mod;}}cout<<res<<endl;
}

F P1928 外星密码 - 洛谷

这题是一个比较难的字符串模拟, 赛时没有想到怎么找最右边那个]对应的[ ,
其实向前一个个判断就可以了,不会超时。。。

tip: 主要要找到最里面的那对[],可以用string 的find方法进行查找,
比如 ss.find("]") , 也可以指定从哪个下标开始查找,ss.find("]",idx) ,不指定默认为0
时间复杂度是O (n * m) ,n为主串长度,m为待查找的子串长度

void solve(){cin>>ss;int r=ss.find(']');//循环直到不存在]while(r!=-1){int l=r;//找到离他最近的[while(ss[l]!='[')l--;//提取这一对[]中所有内容,第一个参数为从哪里提取,第二个参数为提取的串长度string tmp=ss.substr(l+1,r-l-1);string ins="";//cout<<tmp;//处理数字int cnt=0;if(tmp[0]>='0'&&tmp[0]<='9')cnt=cnt*10+tmp[0]-'0';tmp.erase(tmp.begin(),tmp.begin()+1);if(tmp.size()&&tmp[0]>='0'&&tmp[0]<='9'){cnt=cnt*10+tmp[0]-'0';tmp.erase(tmp.begin(),tmp.begin()+1);}//cout<<cnt<<endl;//cout<<tmp;while(cnt--){ins+=tmp;}ss.erase(l,r-l+1);//	cout<<ss<<endl;//将处理后的结果插回到主串中,第一个参数为插入到哪里,第二个参数为插入的字符串ss.insert(l,ins);//cout<<ss;//	break;r=ss.find(']');}cout<<ss;//
}

G P1591 阶乘数码 - 洛谷

高精度,注意idx控制最高位

void solve(){cin>>n>>k;int idx=1;num[1]=1;int tmp=0;for(int i=2;i<=n;i++){for(int j=1;j<=idx||tmp;j++){//这里是一大错点,超过上一次结果范围的地方不要×iif(j<=idx)tmp+=num[j]*i;num[j]=tmp%10;tmp/=10;idx=max(j,idx);}}int res=0;for(int i=idx;i>=1;i--)if(num[i]==k)res++;cout<<res<<endl;
}

H P2234 [HNOI2002] 营业额统计 - 洛谷

震惊,逆天测试样例,暴力就能过了。。。

void solve(){cin>>n;int res=0;for(int i=1;i<=n;i++){cin>>a[i];}res+=a[1];for(int i=2;i<=n;i++){int minv=1e18;for(int j=1;j<i;j++){minv=min(minv,abs(a[i]-a[j]));}res+=minv;}cout<<res<<endl;}

赛后怎么能局限于过题呢?
不能用O(\(n^2\)) , 那正解是什么?

数据结构 set 有一个很好用的k=st.lower_bound(x), 可以在O(n \(log_2 n\))的时间找到set中大于等于x的第一个数,也可以用这个得到小于x的第一个数(k--)
注意lower_bound返回的是一个地址,使用的时候要 * k

void solve(){cin>>n;set<int>st;st.insert(-1e18),st.insert(1e18);int res=0;for(int i=1;i<=n;i++){cin>>a[i];if(i==1){res+=a[i];}else {auto k= st.lower_bound(a[i]);int minv=abs(*k-a[i]);k--;if(*k!=-1e18){minv=min(minv,abs(*k-a[i]));}res+=minv;}st.insert(a[i]);}cout<<res<<endl;
}

I P4447 [AHOI2018初中组] 分组 - 洛谷

赛时没想到怎么写,索性跳过了,暂时想不到的题目可以跳过,等其他题目过了再来看(怎么我越跳越多了💦)

一开始看到想二分答案,但是没想到怎么写check

赛后看到dalao的二分查找, 其实我们可以通过维护两个数组,一个数组用于记录一个小队的长度,另一个用来记录该小队最后一个人期望添加的队友能力值。

Q:怎么知道需要插在哪个小队里还是单开一个呢?多组小队所需能力相同时,怎么确保添加到人数最少的那组呢?
A : 排序,同时排序可以发现,相同值时下标越大,该组的大小越小。

int a[N];
int idx;
int need[N];
int siz[N];
void solve(){cin>>n;for(int i=1;i<=n;i++)cin>>a[i];sort(a+1,a+1+n);need[1]=a[1]+1,siz[1]=1;idx=2;for(int i=2;i<=n;i++){int l=1,r=idx-1;while(l<r){int mid=(l+r+1)>>1;if(need[mid]<=a[i])l=mid;else r=mid-1;}if(need[l]!=a[i]){need[idx]=a[i]+1,siz[idx]=1;idx++;}else {need[l]++,siz[l]++;}}int minv=1e18;for(int i=1;i<idx;i++)minv=min(minv,siz[i]);cout<<minv<<endl;
}

J P3853 [TJOI2007] 路标设置 - 洛谷

二分答案,首先找到单调性:空旷指数越大,所用路标肯定越少

对于两个相邻的路标,如果他们的空旷值小于或等于我们二分出来的x,
那么无需操作;若大于我们的x , 我们就需要使用路标。

需使用个数为$$ \left \lceil \frac{ (a[i]-a[i-1])}{x} \right \rceil -1$$

bool check(int x){int res=0;for(int i=1;i<=n+1;i++){int tmp=a[i]-a[i-1];if(tmp==0)continue;int sum=tmp/x;if(tmp%x)sum++;res+=sum-1;if(res>k)return 0;}return 1;
}
void solve(){cin>>l>>n>>k;for(int i=1;i<=n;i++)cin>>a[i];a[n+1]=l;int l=1,r=10000000;while(l<r){int mid=l+r>>1;if(check(mid))r=mid;else l=mid+1;}cout<<l<<endl;
}

K P2719 搞笑世界杯 - 洛谷

赛时觉得我可以直接用组合数写出来, 但是失败了。。。

线性dp

double f[1300][1300];
//设 f[i][j] 为还剩i张A类免费票,j张B类双倍价钱票时,
//最后两个人拿到两张同样的票的几率
void solve(){cin>>n;n/=2;for(int i=2;i<=n;i++)f[i][0]=f[0][i]=1;//如果只剩一种票了,最后两个人拿到两张同样的票的几率就为1for(int i=1;i<=n;i++){for(int j=1;j<=n;j++){//d[i-1][j](当前同学拿了A类票)和d[i][j-1](当前同学拿了B类票)f[i][j]=f[i][j-1]*0.5+f[i-1][j]*0.5;}}printf("%.4f",f[n][n]);
}

L P1364 医院设置 - 洛谷

链式前向星存图,参考dalao题解:图的遍历:链式前向星详解 - AcWing
之后对每一个点跑一遍bfs就可以啦

#include <bits/stdc++.h>
#define int long long 
#define PII pair<int,int>
#define pb push_back
#define fi first
#define se second
const int N=1e6+10,M=1010,mod=1e9+7;
using namespace std;
int n,m,k;
int h[N],e[N],ne[N],w[N],idx;
struct nod{int id,len;int from;
};
void add(int a,int b){e[idx]=b,ne[idx]=h[a],h[a]=idx++;
} 
void solve(){cin>>n;memset(h,-1,sizeof h);for(int i=1;i<=n;i++){int ww,u,v;cin>>ww>>u>>v;w[i]=ww;if(u){add(i,u),add(u,i);}if(v){add(i,v),add(v,i);}}int minv=1e18;for(int i=1;i<=n;i++){int res=0;queue<nod>qq;qq.push({i,1,i});while(qq.size()){nod tmp = qq.front();qq.pop();for(int i=h[tmp.id];~i;i=ne[i]){int j=e[i];if(j==tmp.from)continue;res+=tmp.len*w[j];qq.push({j,tmp.len+1,tmp.id});if(res>minv)break;}}minv=min(minv,res);}cout<<minv<<endl;
}
signed main(){ios::sync_with_stdio(0);cin.tie(0),cout.tie(0);int _=1;//cin>>_;while(_--)solve();return 0;
} 

M P4145 上帝造题的七分钟 2 / 花神游历各国 - 洛谷

线段树,也看到有dalao用树状数组写:浅谈树状数组 - AcWing
待补。。。

N P2513 [HAOI2009] 逆序对数列 - 洛谷

待补。。。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询