[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';
	}
}
posted @ 2022-08-13 22:30  Hssliu  阅读(44)  评论(0)    收藏  举报