2022/8/10 总结
总结有时间再写吧。在写了在写了。
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;
}

浙公网安备 33010602011771号