#include<bits/stdc++.h>
using namespace std;
typedef long double db;
const int N=23333333;//01串的长度
const db ans=11625907.5798,eps=1e-4;//eps为误差10^-4,保持在这个误差范围内即可
//因为浮点型有有效位,所以肯定有一定误差
int main(){
//整体采用直接暴力的解法
for(int v=0;v<=N/2;++v){//v为0的个数,因为0的个数是小于1的,因此小于总数的一半
int u=N-v;//u为1的个数
db res=-1.0*u*u/N*log2(1.0*u/N)-1.0*v*v/N*log2(1.0*v/N);//log2()函数求log以2为底的对数
if(fabs(res-ans)<eps){//两者相减去绝对值小于误差,则符合条件 fabs函数求绝对值
cout<<v;//输出0的个数
return 0;
}
}
return 0;
}
冶炼金属
cpp复制代码
#include<bits/stdc++.h>
using namespace std;
const int MAX_N=1e4+1;
int N,A[MAX_N],B[MAX_N];
bool check_min(int v){
for(int i=1;i<=N;i++){
if(A[i]/v>B[i])return false;
return true;
}
}
bool check_max( int v){
for(int i=1;i<=N;i++){
if(A[i]/V<B[i])return false;
return true;
}
}
int main(){
ios::sync_with_stdio(0);cin.tie(0);
cin>>N;
for(int i=0;i<=N;i++){
cin>>A[i]>>B[i];
}
int L=1,R=1000000000,V_min;
while(l<R){
int mid=L+R>>1;
if(check_min(mid)){
V_min=mid;
R=mid-1;
}else{
L=mid+1;
}
}
int L=1,R=1000000000,V_max;
while(l<R){
int mid=L+R>>1;
if(check_max(mid)){
V_max=mid;
L=mid+1;
}else{
R=mid-1;
}
}
cout<<v_min<<" "<<v_max;
return 0;
}
飞机降落
cpp复制代码
#include<bits/stdc++.h>
using namespace std;
const int MAX_N=11;
int n;
int N,T[MAX_N],D[MAX_N],L[MAX_N];
bool used[MAX_N],have_answer;
void dfs(int x,int tim){
if(have_answer)return;
if(x==n){
have_answer=1;
return;
}
for(int i=1;i<=n;i++){
if(!used[i]&&tim<=T[i]+D[i])
used[i]=1;
dfs(x+1,max(tim,T[i])+D[i]);
if(have_answer)return;
used[i]=0;
}
}
void solve(){
cin>>N;
for(int i=1;i<=N;i++){
cin>>T[i]>>D[i]>>L[i];
used[i]=0;
}
dfs(0,0);
if(have_answer)cout<<"YES\n";
else cout<<"NO\n";
}
int main(){
ios::sync_with_stdio(0);cin.tie(0);
int T;cin>>T;
while(T--)solve();
return 0;
}
接龙数列
cpp复制代码
#include<bits/stdc++.h>
using namespace std;
const int MAX_N=1e5+5;
int N,dp[10];
int main(){
ios::sync_with_stdio(0);cin.tie(0);
cin>>N;
for(int i=0;i<=N;i++){
int A;cin>>A;
vector<int>d;
while(A){
d.push_back(A%10);
A/10;
}
int y=*d.begin(),x=d.back();
dp[y]=max(dp[y],dp[x]+1);
}
int len=0;
for(int i=0;i<10;i++){
len=max(len,dp[i]);
}
cout<<N-len;
return 0;
}
岛屿数量
cpp复制代码
#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];//对岛进行染色
bool 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};
void bfs_col(int x,int y){
queue<int>qx,qy;
qx.push(x);qy.push(y);vis[x][y]=1;//bfs坐标放进队列后,就标记
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||M<=nx||ny<0||N<=ny||vis[ny][nx]||mp[nx][ny]=='0')continue;//越界或是海水,或被访问过就跳过
qx.push(nx);qy.push(ny);vis[nx][ny]=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;//清空标记,从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;//如果到达边界(到达边界,而不是超越边界),就返回true;
for(int i=0;i<8;i++){
int nx=x+dx[i];
int ny=y+dy[i];
if(nx<0||M<=nx||ny<0||N<=ny||used[ny][nx]||mp[nx][ny]=='1')continue;
qx.push(nx);qy.push(ny);used[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_out(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;
}
cpp复制代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int K;
string S;
char c1,c2;
int main(){
cin>>K>>S>>c1>>c2;
int sum_c1=0;
int n=S.size();
for(int i=k-1,j=0;i<n;i++,j++){
//前缀和,sum_c1记录前面a的数量,当i所在位置为b时,子串简写的数量就是b前面a的数量,不包括前k个位置内的a,
if(S[j]==c1)++sum_c1;
if(S[i]==c2)ans+=sum_c1;
}
cout<<ans;
return 0;
return 0;
}
整数删除
cpp复制代码
#include<bits/stdc++.h>
using namespace std;
#define val first
#define pos second
const int MAX_N=5e5+5;
int N,K,pre[MAX_N],nxt[MAX_N];
typedef long long LL;
typedef pair<LL,int>PLI;
priority_queue<PLI>q;
LL A[MAX_N];
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;
}
景区导游
DFS遍历图(暴力做法)
正解:树上前缀和、最近公共祖先
树:一种数据结构,无环连通图
无环连通图-->任意两个点之间存在唯一的一条路径
2 6 5 1
记作一个点都不去掉之前,总的花费记作sum
(1)去掉2 sum-cost[2->6]
(2)去掉6 sum-cost[2->6]-cost[6->5]+cost[2->5]
(3)去掉5 sum-cost[6->5]-cost[5->1]+cost[6->1]
(4)去掉1 sum-cost[5->1]
暴力做法:DFS:O(n)
优化后的做法,树上前缀和+最近公共祖先O(logn)
图的存储:
链式前向型:链表
vector容器存图
二者的原理: 存储当前点的邻接点
x->y
edge[x].push_back(y);存储了一条x->y的边
无向边的存储,就是存储两条有向边
x-y
edge[x].push_back(y);
edge[y].push_back(x);
DFS组成{
iF()
{ 递归终止的条件
}
往下递归的过程
}
cpp复制代码
#include<bits/stdc++.h>
#define endl '\n'
#define deb(x) cout<<ax<<" = "<<x<<'\n';
#define INF 0x3f3f3f3f
#define int long long
using namespace std;
const int N=2e5+10;
typedef pair<int,int> pii;
map<pil,int>st;//记录从x到y的距离是多少
int a[N];
vector<pii>edge[N];//存图
//dfs的参数不是一下就想到的,而是在写的1过程中发
//现你需要某个信息,而这个信息你没有提前记录 ,
//那么你可以把这个信息当作一个参数,此时就达到了记录信息的目的
//s路程的起点
//v路径的终点
//u你当前走到了哪个点
//father当前这个点的父亲节点是谁,避免重复走
//sum从s走到u的路径花费总和
bool dfs(int s,int u,int father,int v,int sum){
if(u==v){
st[{s,v}]=sum;
st[{v,s}]=sum;
return true;
}
for(int i=0;i<edge[u].size();i++){
int son=edge[u][i].first;
if(son==father){
continue;
}
int w=edge[u][i].second;
if(dfs(s,son,u,v,sum+w))//如果找到了,直接return true即可,剩下的不用遍历;
return true;
}
return false;
}
void solve(){
int n,k;
cin>>n>>k;
for(int i=0;i<n;i++){
int x,y,t;
cin>>x>>y>>t;
edge[x].push_back({y,t});//存图
edge[y].push_back({x,t});
}
for(int i=0;i<k;++){//存路线
cin>>a[i];
}
int ans=0;
for(int i=0;i<k-1;i++){
dfs(a[i],a[i],-1,a[i+1],0);//路线上的点位之间的距离
ans+=st[{a[i],a[i+1]}];
}
for(int i=0;i<k;i++){
int tmp=ans;
/*记作一个点都不去掉之前,总的花费记作sum
(1)去掉2 sum-cost[2->6]
(2)去掉6 sum-cost[2->6]-cost[6->5]+cost[2->5]
(3)去掉5 sum-cost[6->5]-cost[5->1]+cost[6->1]
(4)去掉1 sum-cost[5->1]
*/
if(i==0){
tmp-=st[{a[i],a[i+1]}];
}else if(i==k-1){
tmp-=st[{a[i-1],a[i]}];
}else{
tmp-=st[{a[i-1],a[i]}];
tmp-=st[{a[i],a[i+1]}];
dfs(a[i-1],a[i+1],-1,a[i+1],0);
tmp+=st[{a[i-1],a[i+1]}];
}
cout<<tmp<<endl;
}
}