A
直接 \(O(1)\) 用结论搞出来即可,但赛时发现范围很小就直接模拟了(注意到机器人在撞到上面和左面的墙并发生变速之前一定能够清除,只需要模拟撞下面、右面的墙)
int main(){
int T; cin>>T;
while(T--){
int n, m, sx, sy, tx, ty;
cin>>n>>m>>sx>>sy>>tx>>ty;
int dx=1, dy=1;
int res=0;
rep(i,1,420){
if(sx==tx || sy==ty) break;
if(sx==n) dx=-dx;
if(sy==m) dy=-dy;
sx+=dx, sy+=dy;
res++;
}
cout<<res<<endl;
}
return 0;
}
B
对于每个区间,通过枚举断点,肯定能够找到对应的两个子区间(如果断点在端点那就是一个),模拟即可。
const int N=1010;
pii q[N];
#define x first
#define y second
int main(){
int T; cin>>T;
while(T--){
int n; cin>>n;
set<pii> st;
rep(i,1,n){
int x, y; read(x), read(y);
q[i]={x, y};
st.insert(q[i]);
}
rep(i,1,n){
auto [x, y]=q[i];
if(x==y){
cout<<x<<' '<<x<<' '<<x<<endl;
continue;
}
rep(j,x,y){
if(j==x){
if(st.count({x+1, y})){
cout<<x<<' '<<y<<' '<<x<<endl;
break;
}
}
if(j==y){
if(st.count({x, y-1})){
cout<<x<<' '<<y<<' '<<y<<endl;
break;
}
}
if(st.count({x, j-1}) && st.count({j+1, y})){
cout<<x<<' '<<y<<' '<<j<<endl;
break;
}
}
}
// puts("");
}
return 0;
}
C
对于这种最大化最小值的问题自然是二分。
设现在二分出一个 \(k\),也就是操作后元素都要不小于 \(k\),现在检测其可行性。
考虑贪心,为了防止前面的决策影响后面,我们从后面开始决策:我们自然是想要在保证后面大于 \(k\) 的前提下尽可能将物品分给前面的,最后我们检查一下决策后是否保证所有元素个数大于等于 \(k\) 即可。
const int N=2e5+5;
int a[N], b[N];
int n;
bool ok(int k){
rep(i,1,n) b[i]=a[i];
dwn(i,n,3){
int h=min(a[i]/3, (b[i]-k)/3);
b[i-1]+=h, b[i-2]+=2*h;
}
rep(i,1,n) if(b[i]<k) return false;
return true;
}
signed main(){
int T; cin>>T;
while(T--){
cin>>n;
rep(i,1,n) read(a[i]);
int l=1, r=1e10;
while(l<r){
int mid=l+r+1>>1;
if(ok(mid)) l=mid;
else r=mid-1;
}
cout<<l<<endl;
}
return 0;
}
D
赛时我考虑将机器人可以清扫到污渍的点记为关键点,然后将关键点看成图论中的点,边权是关键点之间的距离,然后得到一个环,但是写挂了呜呜。
后来看了题解才发现可以写得很简单。
记机器人不执行清扫的概率为 \(\overline{p}\)
我们设从出发点出发,期望清扫到污渍的步数为 \(x\),记机器人返回出发点且和最初出发时的朝向的步数为 \(k\)。
设出发点的后继期望清扫到污渍的步数为 \(y\),那么 \(x\) 与 \(y\) 的关系为:\(x=w(1+y)\)。
其中,如果出发点为关键点,那么 \(w=\overline{p}\),否则为 \(1\)。
那么我们有 \(x = w_1(1 + w_2(1 + \dots w_k(1 + x)\dots))\)
发现这其实是一个线性方程,可以化成 \(x=ux+v\) 的形式,因此可以逆向考虑(考虑得到右式),将 \(u,v\) 统计出来,细节见代码。
const int N=1e5+5, mod=1e9+7;
ll fpow(ll x, ll p){
ll res=1;
for(; p; p>>=1, x=x*x%mod)
if(p&1) res=res*x%mod;
return res%mod;
}
ll inv(ll x){
return fpow(x, mod-2)%mod;
}
int add(int a, int b){
return ((a+b)%mod+mod)%mod;
}
int mul(int a, int b){
return a*b%mod;
}
signed main(){
int T; cin>>T;
while(T--){
int n, m, sx, sy, tx, ty, p;
cin>>n>>m>>sx>>sy>>tx>>ty>>p;
p=mul(add(100, -p), inv(100));
int ux=sx, uy=sy;
int u=1, v=0;
int dx=-1, dy=-1;
rep(i,1,4*(n-1)*(m-1)){
if(ux+dx<1 || ux+dx>n) dx=-dx;
if(uy+dy<1 || uy+dy>m) dy=-dy;
ux+=dx, uy+=dy;
v=add(v, 1);
int w;
if(ux==tx || uy==ty) w=p;
else w=1;
u=mul(u, w), v=mul(v, w);
}
cout<<(mul(v, inv(add(1, -u))))<<endl;
}
return 0;
}