2024ccpc郑州(LMFB)
题目链接:第十届中国大学生程序设计竞赛 郑州站(CCPC 2024 Zhengzhou Site) - 比赛主页 - 比赛 - QOJ.ac
L. Z-order Curve
思路
可以发现其实是由一个大的分成四个小的,可以试着用递归来写
这里观察一下l与r的二进制,可以发现从高位到低位开始遍历遇到不同的输出剩余的l即可
代码
void solve(){int l,r;cin>>l>>r;int nowl=0;int ans=0;for(int i=0;i<64;i++){if(((l>>i)&1)!=((r>>i)&1)){ans=nowl;}if((l>>i)&1) nowl+=(1ll<<i);}cout<<ans<<"\n";
}
M. Rejection Sampling
思路
数学题,有一说一我真的很烦这种卡精度的题,因为每次我都调好几发
首先转化题目:
对于某两个方案,选择k-1个相同的数,1个不同的数,就会得到
化简之后可以得到:也就是说,
是个定值,设定值为m,那么
,又因为
可以得到:,因为单调的所以我们可以用二分来求出m来
但这样写出来的代码会TLE,此处有两种修改方案,
1.可以发现m最大为1e18,精度要求1e-6,那么最大的二分次数,可以发现不会超过100次,所以我们直接枚举100次二分过程即可
2.将修改成相对误差
,l越大要求更严格,越小要求更宽松,这样也可以缩减二分次数
代码
#include<bits/stdc++.h>
using namespace std;#define vcoistnt ios_base::sync_with_stdio(false); cin.tie(NULL); cout.tie(NULL);
#define int long long
#define vi vector<int>
#define vb vector<bool>
typedef pair<int,int> pll;
#define double long doubleconst double eps=1e-6;void solve(){int n,k;cin>>n>>k;vector<double> a(n+1);for(int i=1;i<=n;i++){cin>>a[i];}auto cal=[&](double m)->vector<double>{vector<double> p(n+1);for(int i=1;i<=n;i++){p[i]=a[i]/(m+a[i]);}return p;};double l=0,r=1e15;while((r-l)/l>eps){double mid=(l+r)/2;auto p=cal(mid);double sum=accumulate(p.begin()+1,p.begin()+1+n,0.0l);if(sum>k){l=mid;}else{r=mid;}}vector<double> p=cal(l);for(int i=1;i<=n;i++){cout<<p[i]<<"\n";}
}
signed main() {// vcoistntcout<<fixed<<setprecision(12);int _=1;// cin>>_;while(_--) solve();return 0;
}
F. Infinite Loop
思路
可以发现无非就分为了两种情况:
第一天执行的任务可能有剩余需要第二天接着完成,设此剩余时间为res
- res要大于一天中所有任务完成的间隙和,也就是说我们从第二天开始任务之间间就没有间隙了,那么这样的话就以一天完成任务的时间为周期,不断重复了
- res要小于一天中所有任务完成的间隙和,可以发现此种情况,从第二天开始所有的任务在某一天以什么时间开始和结束是一定的
因此我们直接模拟即可
代码
#include<bits/stdc++.h>
using namespace std;#define vcoistnt ios_base::sync_with_stdio(false); cin.tie(NULL); cout.tie(NULL);
#define int long long
#define vi vector<int>
#define vb vector<bool>
typedef pair<int,int> pll;
#define double long doubleconst int N=2e5+10;
const int inf=1e18;
const int mod=998244353;const double eps=1e-6;void solve(){int n,k,q;cin>>n>>k>>q;vector<int> a(n+1),b(n+1);for(int i=1;i<=n;i++){cin>>a[i]>>b[i];}vector<int> ans1(n+1); //记录第一天的答案int now=1; //当前时间int sum=0; //差距for(int i=1;i<=n;i++){if(a[i]>now){sum+=(a[i]-now);now=a[i]+b[i];}else{now=now+b[i];}ans1[i]=now;}auto pri=[&](int x)->void{ //输出时间为x时的真正天数+时间int d=(x-1)/k;int h=(x-1)%k;if((x-1)%k) d++;if(h==0) h=k;cout<<d<<" "<<h<<"\n";};int res=now-k-1;if(res>=sum){ //从第二天的任务开始 每x一个周期vector<int> pre(n+1,0);for(int i=1;i<=n;i++){pre[i]=pre[i-1]+b[i];}while(q--){int x,y;cin>>x>>y;if(x==1){pri(ans1[y]);}else{int v=now+(x-2)*pre[n];v+=pre[y];pri(v);}}}else{ //从第二天开始都是一样的vector<int> ans(n+1);for(int i=1;i<=n;i++){if(a[i]+k>now){now=a[i]+k+b[i];}else{now=now+b[i];}ans[i]=now-k;}while(q--){int x,y;cin>>x>>y;if(x==1){pri(ans1[y]);}else{int v=(x-1)*k;// cout<<v+ans[y]<<"\n";pri(v+ans[y]);}}}
}
signed main() {vcoistntcout<<fixed<<setprecision(12);int _=1;// cin>>_;while(_--) solve();return 0;
}
B. Rolling Stones
思路
此题没什么好说的,BFS最短路,题意思路非常清晰
代码
#include<bits/stdc++.h>
using namespace std;#define vcoistnt ios_base::sync_with_stdio(false); cin.tie(NULL); cout.tie(NULL);
#define int long long
#define vi vector<int>
#define vb vector<bool>
typedef pair<int,int> pll;const int N=2e5+10;
const int inf=1e18;
const int mod=998244353;const int dx[2][3]={{-1,0,0},{1,0,0}}; //上下移动 1的时候可以向下移动,0向上移动
const int dy[2][3]={{-1,-1,1},{1,-1,1}}; //左右移动const int nx[2][5][3]={ //状态0/1 ,当前底面为x,方向为d,下一面为?{ //0 1 2 3 4{},{3,2,4},{4,1,3},{1,4,2},{2,3,1}},{{},{3,4,2},{4,3,1},{1,2,4},{2,1,3}}
};void solve(){int n;cin>>n;vector<vector<int>> g(n+3,vector<int>(2*(n+1)+1)); //存图for(int i=1;i<=n;i++){for(int j=1;j<=2*i-1;j++){cin>>g[i][j];}}int s,e;cin>>s>>e;queue<pll> q;q.push({1,1});vector<vector<int>> dis(n+3,vector<int>(2*(n+1)+1,-1));dis[1][1]=0;while(!q.empty()){auto [x,y]=q.front();q.pop();int bf=y%2;for(int i=0;i<3;i++){ //三个方向int xx=x+dx[bf][i]; //计算所去往的点int yy=y+dy[bf][i];if(g[xx][yy]==0||dis[xx][yy]!=-1) continue; //非法位置if(g[xx][yy]==nx[bf][g[x][y]][i]){ //判断数是否一致dis[xx][yy]=dis[x][y]+1;q.push({xx,yy});}}}cout<<dis[s][e]<<"\n";
}
signed main() {vcoistntcout<<fixed<<setprecision(2);int _=1;// cin>>_;while(_--) solve();return 0;
}
