2022/8/10 总结

题目是洛谷 P7523 U237177 U237170

总结有时间再写吧。在写了在写了。

A.Cytoid

  • 要不是我打过 Phigros 题面都看不懂罢 题外话,可以看看这个;

Solution

  • 虽然大佬的做法是 \(\mathtt{DP}\),然而我是暴力过的;

  • 开两个二维树状数组,一个存 x 一个存 ?,然后跑一遍预处理出每个点树状数组查询的结果,再枚举每个点,计算每个点向右下方拓展出矩阵数的期望,加入答案即可;

AC code
#include<bits/stdc++.h>
using namespace std;

const int mod=998244353;

#define ll long long

int n,m;
char ch;
int num[105][105];
int c[2][105][105];
int cn[2][105][105];
int cnt=0;
ll ans=0;

ll ksm(int a,int b){
	ll cnt=1,x=a;
	for(;b;b>>=1,(x*=x)%=mod)
		if(b&1)
			(cnt*=x)%=mod;
	return cnt;
}

void add(int o,int x,int y,int v){
	for(;x<=n;x+=x&-x)
		for(int j=y;j<=m;j+=j&-j)
			c[o][x][j]+=v;
	return ;
}

ll ask(int o,int x,int y){
	ll cnt=0;
	for(;x;x-=x&-x)
		for(int j=y;j;j-=j&-j)
			cnt+=c[o][x][j];
	return cnt;
}

int get(int o,int a,int b,int c,int d){
	long long cnt=0;
	(cnt+=cn[o][c][d]-cn[o][a-1][d]-cn[o][c][b-1]+cn[o][a-1][b-1])%=mod;
	return (int)cnt;
}

void count(int x,int y){
	if(get(0,x,y,x,y)) return ;
	for(int a=x;a<=n;++a){
		for(int b=y;b<=m;++b){
			if(get(0,x,y,a,b)) continue;
			ll k=get(1,x,y,a,b);
			if(!k) ++ans;
			else{
				int v=ksm(2,k);
				(ans+=1ll*ksm(v,mod-2))%=mod;
			}
		}
	}
	return ;
}

int main(){
//	freopen("cai.in","r",stdin);
//	freopen("cai.out","w",stdout);
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;++i){
		for(int j=1;j<=m;++j){
			cin>>ch;
			if(ch=='x')
				add(0,i,j,1);
			if(ch=='?')
				add(1,i,j,1);
		}
	}
	for(int i=1;i<=n;++i){
		for(int j=1;j<=m;++j){
			cn[0][i][j]=ask(0,i,j);
			cn[1][i][j]=ask(1,i,j);
		}
	}
	for(int i=1;i<=n;++i){
		for(int j=1;j<=m;++j){
			count(i,j);
		}
	}
	printf("%lld",ans);
	return 0;
}

B.串

Solution

  • 貌似是道 \(\mathtt{AC}\) 自动机为什么不是自动 AC 机;

C.灯

  • 题意:有一串长度为 \(n\) 的数字,每个都在 \(0\sim 9\) 之间,给出一些操作,每次询问一个区间 \([l,r]\) 的数字之和,然后将这个区间中的每个数都 \(+1\),如果出现进位的情况只保留个位;

  • 考场挂了分是因为样例太水转移状态有点小问题;

Solution

  • 线段树和分块都可做(甚至线段树的代码可能比分块更短);

  • 每个节点记录一个 \(sum\) 表示数字和,和一个 \(num[\ ]\) 数组记录这个区间中个位为 \(i\) 的有多少个;

AC code
#include<bits/stdc++.h>
using namespace std;

inline int read(){
	int s=0,f=1;
	char ch=getchar();
	while(!isdigit(ch)){
		if(ch=='-') f=-1;
		ch=getchar();
	}
	while(isdigit(ch)){
		s=s*10+int(ch-'0');
		ch=getchar();
	}
	return s*f;
}

const int N=25e4+10;

int n,m;
string str;

struct memr{
	int l,r,siz,tg;
	int sum,num[11];
}tr[N<<3];

void pushup(int p){
	tr[p].sum=tr[p<<1].sum+tr[p<<1|1].sum;
	for(int i=0;i<10;++i)
		tr[p].num[i]=tr[p<<1].num[i]+tr[p<<1|1].num[i];
	return ;
}

void add(int p,int x){
	if(!x) return ;
	x%=10;
	int lsum=0;
	for(int i=10-x;i<10;++i)
		lsum+=tr[p].num[i];
	tr[p].sum+=x*tr[p].siz-lsum*10;
	int a[10];
	for(int i=0;i<10;++i)
		a[i]=tr[p].num[i];
	for(int i=0;i<10;++i)
		tr[p].num[(i+x)%10]=a[i];
	return ;
}

void pushdown(int p){
	tr[p].tg%=10;
	if(tr[p].tg){
		add(p<<1,tr[p].tg);
		add(p<<1|1,tr[p].tg);
		tr[p<<1].tg+=tr[p].tg;
		tr[p<<1|1].tg+=tr[p].tg;
		tr[p].tg=0;
	}
	return ;
}

void change(int p,int l,int r){
	if(l<=tr[p].l && tr[p].r<=r){
		add(p,1);
		(tr[p].tg+=1)%=10;
		return ;
	}
	pushdown(p);
	int mid=(tr[p].l+tr[p].r)>>1;
	if(l<=mid) change(p<<1,l,r);
	if(mid<r) change(p<<1|1,l,r);
	pushup(p);
	return ;
}

int ask(int p,int l,int r){
	if(l<=tr[p].l && tr[p].r<=r){
		return tr[p].sum;
	}
	pushdown(p);
	int cnt=0;
	int mid=(tr[p].l+tr[p].r)>>1;
	if(l<=mid) cnt+=ask(p<<1,l,r);
	if(mid<r) cnt+=ask(p<<1|1,l,r);
	pushup(p);
	return cnt;
}

void build(int p,int l,int r){
	tr[p].l=l,tr[p].r=r;
	tr[p].siz=r-l+1;
	tr[p].tg=0;
	if(l==r){
		tr[p].sum=int(str[l-1]-'0');
		++tr[p].num[tr[p].sum];
		return ;
	}
	int mid=(l+r)>>1;
	build(p<<1,l,mid);
	build(p<<1|1,mid+1,r);
	pushup(p);
	return ;
}

int main(){
	n=read(),m=read();
	cin>>str;
	int l,r;
	build(1,1,n);
	while(m--){
		l=read(),r=read();
		printf("%d\n",ask(1,l,r));
		change(1,l,r);
	}
	return 0;
}
posted @ 2022-08-10 21:45  Star_LIcsAy  阅读(65)  评论(0)    收藏  举报