2022.11.11题解

一测:\(300pts\)

T1:预估绿(1600)。

T2:String Reversal(蓝)

T3:XOR Inverse(蓝)


T1:


题意简述:

给定一个 \(n\times m\) 的带墙体平面图,一个点有 \(\frac{1}{2}\) 的概率建造灯塔,灯塔可以照亮上下左右四个方向所有点,不能穿过墙,问被照亮的点的个数的期望值,对 \(1e9+7\) 取模。


解:

直接找到一个点上下左右所有点,如果有 \(k\) 个,那么这个点被点亮概率为 \(\frac{2^k-1}{2^k}\)

把所有的点期望加起来即可。

#include<iostream>
#include<cstdio>
#define int long long
using namespace std;
const int N=2005;
const int M=10005;
const int mod=1000000007;
int p[M],n,m,a[N][N];
char s[N][N];
int quick_pow(int x,int y)
{
	int sum=1,num=x;
	while(y)
	{
		if(y&1)sum*=num,sum%=mod;
		num*=num;
		num%=mod;
		y>>=1;
	}
	return sum;
}
signed main()
{

	scanf("%lld%lld",&n,&m);
	int num=1;
	p[0]=0;
	for(int i=1;i<=10000;i++)
	{
		num*=2;
		num%=mod;
		p[i]=((num-1+mod)%mod)*quick_pow(num,mod-2)%mod;
	}
	for(int i=1;i<=n;i++)scanf("%s",s[i]+1);
	for(int i=1;i<=n;i++)
	{
		int sum=0;
		for(int j=1;j<=m;j++)
		{
			if(s[i][j]=='#')sum=0;
			else sum++;
			a[i][j]+=sum;
		}
		sum=0;
		for(int j=m;j>=1;j--)
		{
			if(s[i][j]=='#')sum=0;
			else sum++;
			a[i][j]+=sum;
		}
	}
	for(int j=1;j<=m;j++)
	{
		int sum=0;
		for(int i=1;i<=n;i++)
		{
			if(s[i][j]=='#')sum=0;
			else sum++;
			a[i][j]+=sum;
		}
		sum=0;
		for(int i=n;i>=1;i--)
		{
			if(s[i][j]=='#')sum=0;
			else sum++;
			a[i][j]+=sum;
		}
	}
	for(int i=1;i<=n;i++)for(int j=1;j<=m;j++)if(s[i][j]=='.')a[i][j]-=3;
	int ans=0;
	for(int i=1;i<=n;i++)for(int j=1;j<=m;j++)ans+=p[a[i][j]],ans%=mod;
	printf("%lld",ans);
	return 0;
}

T2:

题意简述:

给定一个字符串,将字符串倒置,每次操作可以交换相邻的两个字母,问最少用多少步可以将字符串还原。


解:

可以预处理出来所有字母从前往后的位置,每次从前往后还原一个字母,那么一定是将离的最近的字母转移过来,交换时会影响在这个字母之前的所有字母位置,用树状数组记录往左移了几格即可。

#include<iostream>
#include<cstdio>
#define int long long
using namespace std;
const int N=2e5+5;
int n,t[26][N],len[26],f[N];
char s1[N],s2[N];
inline int lowbit(int x)
{
	return x&(-x);
}
void update(int x,int k)
{
	while(x<=n)
	{
		f[x]+=k;
		x+=lowbit(x);
	}
}
int search(int x)
{
	int num=0;
	while(x)
	{
		num+=f[x];
		x-=lowbit(x);
	}
	return num;
}
signed main()
{
	scanf("%lld",&n);
	scanf("%s",s1+1);
	for(int i=1;i<=n;i++)s2[i]=s1[n-i+1];
	for(int i=n;i>0;i--)t[s2[i]-'a'][++len[s2[i]-'a']]=i;
	int ans=0;
	for(int i=1;i<=n;i++)
	{
		ans+=search(t[s1[i]-'a'][len[s1[i]-'a']])+t[s1[i]-'a'][len[s1[i]-'a']]-i;
		update(t[s1[i]-'a'][len[s1[i]-'a']]+1,-1);
		update(1,1);
		len[s1[i]-'a']--;
	}
	printf("%lld",ans);
	return 0;
}

T3:


题意简述:

给定一个序列,求最小的 \(x\) 使得序列中所有数异或 \(x\) 后逆序对最少。

分位处理,对于每一位求顺序对与逆序对,然后分组向下递归。最后处理每一位,如果这一位顺序对比逆序对少,那么选取这一位来对所有数异或即可。

#include<iostream>
#include<cstdio>
#include<algorithm>
#define int long long 
using namespace std;
const int N=3e5+5;
int n,a[N],ans,f[N],cnt,p1[35],p2[35];
struct node
{
	int data,name;
}t[N],s[N];
int cmp(node fi,node se)
{
	if(fi.data==se.data)return fi.name<se.name;
	return fi.data<se.data;
}
int cmp2(node fi,node se)
{
	return fi.name<se.name;
}
inline int lowbit(int x)
{
	return x&-x;
}
void update(int x)
{
	while(x)
	{
		f[x]++;
		x-=lowbit(x);
	}
}
int search(int x)
{
	int sum=0;
	while(x<=cnt)
	{
		sum+=f[x];
		x+=lowbit(x);
	}
	return sum;
}
void dfs(int i,int beg,int ed)
{
	if(beg>=ed)return;
	if(i<0)return;
	bool ss=((a[beg]&(1<<i)));
	int bef=beg,sum1=0,sum2=0,tot1=0,tot2=0;
	for(int j=beg;j<=ed;j++)
	{	
		int x=s[j].name;
		if(((a[x]&(1<<i))>0)!=ss)
		{
			if(ss==1)tot1+=sum2*(j-bef);
			if(ss==0)tot2+=sum1*(j-bef);
			ss=((a[x]&(1<<i)));
			bef=j;
		}
		sum1+=((a[x]&(1<<i))>0),sum2+=((a[x]&(1<<i))==0);
		s[j].data=((a[x]&(1<<i))>0);
	}
	sort(s+beg,s+ed+1,cmp);
	if(ss==1)tot1+=sum2*(ed-bef+1);
	if(ss==0)tot2+=sum1*(ed-bef+1);
	dfs(i-1,beg,ed-sum1);
	dfs(i-1,beg+sum2,ed);
	p1[i]+=tot1;
	p2[i]+=tot2;
}
signed main()
{
	scanf("%lld",&n);
	for(int i=1;i<=n;i++)scanf("%lld",&a[i]),s[i].name=i;
	dfs(30,1,n);
	for(int i=0;i<=30;i++)if(p2[i]>p1[i])ans^=(1<<i);
	for(int i=1;i<=n;i++)
	{
		t[i].name=i;
		t[i].data=a[i]^ans;
	}
	sort(t+1,t+1+n,cmp);
	int bef=-1;
	for(int i=1;i<=n;i++)
	{
		if(t[i].data!=bef)cnt++;
		bef=t[i].data;
		t[i].data=cnt;
	}
	sort(t+1,t+1+n,cmp2);
	int tot=0;
	for(int i=1;i<=n;i++)
	{
		tot+=search(t[i].data+1);
		update(t[i].data);
	}
	printf("%lld %lld",tot,ans);
	return 0;
}
posted @ 2023-02-24 14:00  Gmt丶Fu9ture  阅读(21)  评论(0)    收藏  举报