[2022杭电多校1] 更新至3题
1011 Random
题意:给定\(n\)个\([0,1]\)区间的数,做\(m\)次操作,每次1/2几率删去最大数,1/2几率删去最小数,问剩下数的和的期望对1e9+7取模的结果
其实全看成\(n\)个\(0.5\)即可,答案是\((n-m)/2\)再对p取模,除以2要变成乘2的乘法逆元
#include<bits/stdc++.h>
using namespace std;
#define int long long
int n,m,p=1e9+7;
int qmi(int a,int b,int p)
{
int res=1;
for(;b;b>>=1,a=a*a%p)
if(b&1) res=res*a%p;
return res;
}
main()
{
int t;cin>>t;
while(t--)
{
cin>>n>>m;
cout<<(n-m)*qmi(2,p-2,p)%p<<'\n';
}
}
1012 Alice and Bob
题意:黑板上有m个0~n的数,Alice每次可以把这些数划分成两个集合,Bob可以使一个集合内的数被删除,同时另一个集合内的所有数-1,在任何时候,如果黑板上有数字0则Alice胜,如果黑板上没有数字了则Bob胜,若两人都采取最佳策略,输出谁赢得游戏
如果初始0的个数大于0,则Alice必胜。如果有两个1,可以转化为1个0,Alice必胜。如果有4个2,可以转化为2个1,再转为1个0,Alice必胜。
但如果有1个1和2个2,采取(1|2 2),删左减右的策略可以转化为(1 1),再转化为0,即一对i可以贡献一个i-1。
第一发wa了,没有考虑两个a[i]可以产生一个a[i-1],只考虑了如果a[i]>=2^i则Alice必胜
正确的做法是从后往前扫一遍,使a[i-1]+=a[i]/2,判断a[0]是否大于0即可。
输入输出量较大,搞点解除输入输出流
#include<bits/stdc++.h>
using namespace std;
#define int long long
int t,n,m;
int a[1010100];
main()
{
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
cin>>t;
while(t--)
{
cin>>n;
for(int i=0;i<=n;i++)
cin>>a[i];
for(int i=n;i>0;i--) a[i-1]+=a[i]/2;
if(a[0]) cout<<"Alice"<<'\n';
else cout<<"Bob"<<'\n';
}
}
1002 Dragon Slayer
题意:给定一个矩形网格图的长宽n和m,给定勇士所在的网格和龙所在的网格,给定K个在网格线上的墙的左右顶点的坐标,勇士不能穿墙或穿过区域,但可以使用魔法使一堵墙永远消失。问从勇士所在的网格走到龙所在的网格需要的最少使用魔法次数。
注意到n,m,K<=15,意味着可以搜索&暴力枚举
首先将线化成格,改变坐标,使位于网格上的坐标2,位于网格线上的坐标2+1。
使用二进制状态0~(1<<K-1),第i位为1表示不破坏第i堵墙,否则表示破坏墙。针对每种状态bfs一遍判断是否能到达终点,如果能则写出当前状态1的个数cnt,更新ans为min(ans,k-cnt)。
小剪枝:lowbit先判断当前状态下1的个数c,若ans<=k-c(ans小于这种状态下需要破坏的墙数),则可直接跳过这种状态,否则会tle(悲
#include<bits/stdc++.h>
using namespace std;
const int N=100;
bool st[N][N];
int xs,ys,xt,yt;
int n,m,K,t;
int ans=0x3f3f3f3f;
int d1[4]={0,1,0,-1};
int d2[4]={1,0,-1,0};
struct node{
int x,y;
};
struct node1{
int x1,y1,x2,y2;
}wall[N];
void bfs(int x)
{
memset(st,0,sizeof st);
int cnt=0;
for(int i=0;i<K;i++)
{
if(x&1)
{
cnt++;
int xq=wall[i].x1,yq=wall[i].y1,xz=wall[i].x2,yz=wall[i].y2;
if(xq==xz)
{
if(yq>yz) swap(yq,yz);
for(int j=yq;j<=yz;j++) st[xq][j]=1;
}
if(yq==yz)
{
if(xq>xz) swap(xq,xz);
for(int j=xq;j<=xz;j++) st[j][yq]=1;
}
}
x>>=1;
}
queue<node> q;
q.push({xs,ys});
st[xs][ys]=1;
while(!q.empty())
{
node w=q.front();q.pop();
if(w.x==xt&&w.y==yt)
{
ans=min(ans,K-cnt);
return;
}
for(int k=0;k<4;k++)
{
int tx=w.x+d1[k],ty=w.y+d2[k];
if(st[tx][ty]!=1&&tx>0&&tx<=2*n&&ty>0&&ty<=2*m)
{
st[tx][ty]=1;q.push({tx,ty});
}
}
}
}
main()
{
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
cin>>t;
while(t--)
{
ans=0x3f3f3f3f;
cin>>n>>m>>K;
cin>>xs>>ys>>xt>>yt;
xs=xs*2+1,ys=ys*2+1,xt=xt*2+1,yt=yt*2+1;
for(int i=0;i<K;i++)
{
int x1,y1,x2,y2;cin>>x1>>y1>>x2>>y2;
wall[i]={x1*2,y1*2,x2*2,y2*2};
}
for(int i=0;i<(1<<K);i++)
{
int cnt=0;
for(int j=i;j;j-=j&-j) cnt++;
//cout<<cnt;
if(cnt<=K-ans) continue;
bfs(i);
}
cout<<ans<<'\n';
}
}

浙公网安备 33010602011771号