The 19th Zhejiang Provincial Collegiate Programming Contest

Preface

来点强省的省赛,结果发现ZJCPC的题比想象中的友好很多

这场前期算是比较顺利,很快地一遍过了F后然后稳健出题

后期徐神直接开出造计算机题把题数带到两位数,但另一边我和祁神写的E题因为一种情况细节比较恶心一直WA到了比赛结束

评价是我真不太会写这种细节很多的DP题,下次得早点丢给徐神写的说


A. JB Loves Math

签到题,注意操作次数上限为\(3\),分类讨论即可

#include<cstdio>
#include<iostream>
#define RI register int
#define CI const int&
using namespace std;
int t,a,b;
int main()
{
	for (scanf("%d",&t);t;--t)
	{
		scanf("%d%d",&a,&b);
		if (a==b) { puts("0"); continue; }
		if (a<b&&(b-a)%2==1) { puts("1"); continue; }
		if (a>b&&(a-b)%2==0) { puts("1"); continue; }
		if (a<b&&((b-a)/2)%2==1) { puts("2"); continue; }
		if (a>b) { puts("2"); continue; }
		puts("3");
	}
	return 0;
}

B. JB Loves Comma

纯签到,但出题人好像对cjb不是很友好啊

#include<cstdio>
#include<iostream>
#include<string>
#define RI register int
#define CI const int&
using namespace std;
int main()
{
	ios::sync_with_stdio(false); cin.tie(0);
	string s; cin>>s; string t;
	for (RI i=0;i<s.size();++i)
	{
		t+=s[i];
		if (i>=2&&s[i-2]=='c'&&s[i-1]=='j'&&s[i]=='b') t+=",";
	}
	return cout<<t,0;
}

C. JB Wants to Earn Big Money

徐神开场写的签,我题面都没看

#include <bits/stdc++.h>

int main() {
	std::ios::sync_with_stdio(false);
	int n, m, x, ans = 0;
	std::cin >> n >> m >> x;
	for(int i = 0, a; i < n; ++i) {
		std::cin >> a;
		ans += (a >= x);
	}
	for(int i = 0, b; i < m; ++i) {
		std::cin >> b;
		ans += (b <= x);
	}
	std::cout << ans << char(10);
	return 0;
}

D. The Profiteer

疑似本场防AK题,直接弃疗


E. Easy Jump

唉空洞骑士,让闪总想起了去年在桂林电脑被徐神支配的恐惧

这题刚开始看数据范围想着用个暴力迭代\(1000\)次的马尔可夫过程上去乱搞,但后面写了一个version后发现样例都过不去

后面冷静下来发现原来状态要从后往前推,然后在下面思考的时候发现这题其实是有贪心策略的

首先考虑\(S=0\or T1\ge T2\)的情况,此时显然我们不会用MP来回血,因此最优策略就是在每个点能Try就Try,直到血量为\(1\)时再用一次回血

考虑用\(f_{i,j}\)表示在点\(i\),HP为\(j\),走到终点的期望时间,转移的话会有一种Case成环,但可以通过移项解决

现在问题是对于一般的情况,显然用MP回血更优,因此此时策略就变为了先一直Try到血量为\(1\),然后如果有MP就用MP回血,否则再自然回血

把上面的DP状态扩充为\(f_{i,j,k}\),表示在点\(i\),HP为\(j\),MP为\(k\)到终点的期望时间,在没有圣坛的地方转移是很trivial的

现在的问题是当引入圣坛时,最优的策略可能是先在前面的圣坛用MP回一部分血,然后再往后面走

因此在圣坛的时候转移需要特别注意,同时要钦定状态的第三维始终为\(S\)

比赛的时候写了很多铸币实现全是错的,赛后看了别人代码才发现一种好理解的写法

考虑之前我们把回血的阈值默认定为\(2\),现在不妨枚举这个阈值\(x\),显然血量为\(x\)的情况由于成环可以直接解除

然后对于血量\(j<x\)的状态,它们的含义就是在\(i\)这个圣坛处选择先回一部分血,因此贡献是每次递增\(T1\)

而对于血量\(j>x\)的状态,还是用和之前类似的方法转移,而扣一滴血的后继状态也可以递推求出

具体实现看代码,复杂度\(O(N\times H\times S)\)

#include<cstdio>
#include<iostream>
#include<cmath>
#define double long double
#define RI register int
#define CI const int&
using namespace std;
const int N=1005;
const double INF=1e18;
int n,H,S,p[N],k,x,T1,T2,st[N]; double P[N];
namespace Case1
{
	double f[N][10];
	inline void solve(void)
	{
		for (RI i=n,j;i>=1;--i) for (j=2;j<=H;++j)
		if (j>2) f[i][j]=1.0+f[i+1][j]*P[i]+f[i][j-1]*(1.0-P[i]);
		else f[i][j]=(1.0+f[i+1][j]*P[i]+T2*(1.0-P[i]))/P[i];
		printf("%.12Lf",f[1][H]);
	}
};
namespace Case2
{
	double f[N][10][10];
	inline void solve(void)
	{
		for (RI i=n,j,k,x;i>=1;--i)
		{
			if (st[i])
			{
				for (j=2;j<=H;++j) for (k=0;k<=S;++k) f[i][j][k]=INF;
				static double g[10]; for (x=2;x<=H;++x)
				{
					g[x]=(1.0+f[i+1][x][S]*P[i]+T1*(1.0-P[i]))/P[i];
					for (j=x-1;j>=2;--j) g[j]=g[j+1]+T1;
					for (j=x+1;j<=H;++j) g[j]=1.0+f[i+1][j][S]*P[i]+g[j-1]*(1.0-P[i]);
					for (j=2;j<=H;++j) f[i][j][S]=min(f[i][j][S],g[j]);
				}
				for (j=2;j<=H;++j) for (k=0;k<S;++k) f[i][j][k]=f[i][j][S];
			} else
			{
				for (j=2;j<=H;++j) for (k=0;k<=S;++k)
				{
					if (j>2) { f[i][j][k]=1.0+f[i+1][j][k]*P[i]+f[i][j-1][k]*(1.0-P[i]); continue; }
					if (k>0) f[i][j][k]=1.0+f[i+1][j][k]*P[i]+(f[i][j][k-1]+T1)*(1.0-P[i]);
					else f[i][j][k]=(1.0+f[i+1][j][k]*P[i]+T2*(1.0-P[i]))/P[i];
				}
			}
		}
		printf("%.12Lf",f[1][H][S]);
	}
};
int main()
{
	RI i; for (scanf("%d%d%d",&n,&H,&S),i=1;i<=n;++i)
	scanf("%d",&p[i]),P[i]=1.0*p[i]/100.0;
	for (scanf("%d",&k),i=1;i<=k;++i) scanf("%d",&x),st[x]=1;
	scanf("%d%d",&T1,&T2);
	if (S==0||T2<=T1) Case1::solve(); else Case2::solve();
	return 0;
}

F. Easy Fix

简单分类讨论+DS题,今天手感也很好上去刚码完就一发过编译一发过样例,交上去也一发入魂

首先初始局面下每个点的\(a_i,b_i\)可以用树状数组算出,这个非常的trivial

考虑钦定交换的\(u<v\),显然\([1,u-1],[v+1,n]\)这段区间的贡献不受影响,可以用前缀和先处理出来

对于\(u,v\)这两个数本身,它们的\(a_u,b_u,a_v,b_v\)的影响简单讨论下就是要求\([u,v-1]\)或者\([u+1,v]\)\(<p_u/p_v\)的数的个数,这个拿个主席树维护一下即可

然后就是对于\(i\in[u+1,v-1]\)中的数,考虑交换对它们的影响

显然若\(p_i<p_u\and p_i<p_v\)或者\(p_i>p_u\and p_i>p_v\)​,则交换后它们的贡献不变

否则以\(p_u<p_i<p_v\)为例,此时\(a_i\)会减\(1\)\(b_i\)会加\(1\),我们直接把\(\min(a_i-1,b_i+1)\)的值预先维护一下,扔到主席树上查询即可;\(p_u>p_i>p_v\)的情形类似

综上直接以\(p_i\)为下标搞一个主席树,每个点存个数以及三种情况的贡献即可,代码其实也很好写

#include<cstdio>
#include<iostream>
#include<array>
#define int long long
#define RI register int
#define CI const int&
using namespace std;
const int N=100005;
typedef array <int,4> Q;
int n,p[N],q,u,v,a[N],b[N],pfx[N],rt[N];
class Tree_Array
{
	private:
		int bit[N];
	public:
		#define lowbit(x) (x&-x)
		inline void add(RI x,CI y)
		{
			for (;x<=n;x+=lowbit(x)) bit[x]+=y;
		}
		inline int get(RI x,int ret=0)
		{
			for (;x;x-=lowbit(x)) ret+=bit[x]; return ret;
		}
		#undef lowbit
}BIT;
class Segment_Tree
{
	private:
		struct segment
		{
			int ls,rs,val[4];
		}O[N*40]; int tot;
	public:
		inline void insert(int& x,CI y,CI pos,const Q& arr,CI l=1,CI r=n)
		{
			O[x=++tot]=O[y]; for (RI i=0;i<4;++i) O[x].val[i]+=arr[i];
			if (l==r) return; int mid=l+r>>1;
			if (pos<=mid) insert(O[x].ls,O[y].ls,pos,arr,l,mid);
			else insert(O[x].rs,O[y].rs,pos,arr,mid+1,r);
		}
		inline int query(CI x,CI y,CI beg,CI end,CI tp,CI l=1,CI r=n)
		{
			if (beg<=l&&r<=end) return O[y].val[tp]-O[x].val[tp]; int mid=l+r>>1,ret=0;
			if (beg<=mid) ret+=query(O[x].ls,O[y].ls,beg,end,tp,l,mid);
			if (end>mid) ret+=query(O[x].rs,O[y].rs,beg,end,tp,mid+1,r);
			return ret;
		}
}SEG;
signed main()
{
	RI i; for (scanf("%lld",&n),i=1;i<=n;++i) scanf("%lld",&p[i]);
	for (i=1;i<=n;++i) a[i]=BIT.get(p[i]),BIT.add(p[i],1);
	for (i=1;i<=n;++i) BIT.add(p[i],-1);
	for (i=n;i>=1;--i) b[i]=BIT.get(p[i]),BIT.add(p[i],1);
	for (i=1;i<=n;++i) pfx[i]=pfx[i-1]+min(a[i],b[i]);
	for (i=1;i<=n;++i) SEG.insert(rt[i],rt[i-1],p[i],{1,min(a[i],b[i]),min(a[i]-1,b[i]+1),min(a[i]+1,b[i]-1)});
	for (scanf("%lld",&q),i=1;i<=q;++i)
	{
		scanf("%lld%lld",&u,&v); if (u>v) swap(u,v);
		if (u==v) { printf("%lld\n",pfx[n]); continue; }
		int ans=pfx[u-1]+pfx[n]-pfx[v],tmp;
		auto ask=[&](CI l,CI r,CI beg,CI end,CI tp)
		{
			if (l>r||beg>end) return 0LL;
			return SEG.query(rt[l-1],rt[r],beg,end,tp);
		};
		tmp=ask(u+1,v,1,p[u],0); ans+=min(a[u]+tmp,b[u]-tmp);
		tmp=ask(u,v-1,1,p[v],0); ans+=min(a[v]-tmp,b[v]+tmp);
		if (p[u]<p[v])
		{
			ans+=ask(u+1,v-1,1,p[u]-1,1);
			ans+=ask(u+1,v-1,p[v]+1,n,1);
			ans+=ask(u+1,v-1,p[u]+1,p[v]-1,2);
		} else
		{
			ans+=ask(u+1,v-1,1,p[v]-1,1);
			ans+=ask(u+1,v-1,p[u]+1,n,1);
			ans+=ask(u+1,v-1,p[v]+1,p[u]-1,3);
		}
		printf("%lld\n",ans);
	}
	return 0;
}

G. Easy Glide

祁神一眼秒的一个几何+Dijkstra,我题面都没看就不做评价了

#include<bits/stdc++.h>
using namespace std;
#define int long long

using LD = long double;
const LD INF = 4e18+5;
const int N = 1005;
const LD eps = 1e-8;
int sgn(LD x){return fabs(x)<=eps ? 0 : (x>eps ? 1 : -1);}

int n, v1, v2;
LD dis[N][N];

bool inD[N]; LD dis2[N];
struct Node{
	LD dis; int x;
	bool operator<(const Node &b)const{return sgn(dis-b.dis)>0;}
};
priority_queue<Node> Q;

struct Pt{
	int x, y;	
	Pt operator-(const Pt &b)const{return Pt{x-b.x, y-b.y};}
	LD len(){return sqrtl(x*x+y*y);}
}pt[N];

signed main(){
	ios::sync_with_stdio(0); cin.tie(0);
	cout << setiosflags(ios::fixed) << setprecision(12);
	cin >> n;
	for (int i=1; i<=n; ++i){
		cin >> pt[i].x >> pt[i].y;	
	}
	cin >> pt[0].x >> pt[0].y >> pt[n+1].x >> pt[n+1].y;
	cin >> v1 >> v2;
	for (int j=1; j<=n+1; ++j) dis[0][j] = (pt[0]-pt[j]).len()/v1;
	for (int i=1; i<=n; ++i){
		for (int j=1; j<=n+1; ++j){
			if (i==j) continue;
			LD len = (pt[i]-pt[j]).len();
			if (sgn(3*v2-len) >= 0) dis[i][j] = len/v2;
			else dis[i][j] = 3 + (len-3*v2)/v1;
		}
	}
	
//	for (int i=0; i<=n+1; ++i){
//		for (int j=0; j<=n+1; ++j) cout << dis[i][j] << (j==n+1 ? '\n' : ' ');
//	}
	
	for (int i=1; i<=n+1; ++i) dis2[i]=INF;
//	for (int i=0; i<=n+1; ++i){
//		cout << dis2[i] << (i==n+1 ? '\n' : ' ');
//	}
	dis2[0]=0.0L;
	Q.push(Node{0.0L, 0});
	while (!Q.empty()){
		int x = Q.top().x; Q.pop();
		if (inD[x]) continue; inD[x]=true;
		for (int v=1; v<=n+1; ++v){
			if (v==x) continue;
			if (sgn(dis2[v] - (dis2[x]+dis[x][v]))>=0){
				dis2[v] = dis2[x]+dis[x][v];
//				printf("x=%lld v=%lld dis2[v]=%Lf\n", x, v, dis2[v]);
				Q.push(Node{dis2[v], v});
			}
		}
	}
//	for (int i=0; i<=n+1; ++i){
//		cout << dis2[i] << (i==n+1 ? '\n' : ' ');
//	}
	cout << dis2[n+1] << '\n';
	return 0;	
}

H. A=B

论徐神为什么是神,凡是这种造计算机类的题都完全难不住徐神,看来徐神的称号又要加上一个造计算机 master了

这题虽然徐神和我讲了下题意但我也没太听懂,后面徐神讲做法的时候我在E题坐牢也不知道怎么写,反正徐神牛逼就对了

#include <iostream>

#define o std::cout <<
#define e << std::endl;

int main() {
	o "DZ=(return)1" e
	o "S=TZ" e
	o "Za=AZ" e
	o "Zb=BZ" e
	o "Zc=CZ" e
	o "aZ=Z" e
	o "bZ=Z" e
	o "cZ=Z" e
	for(int i = 0; i < 3; ++i) for(int j = 0; j < 3; ++j) for(int k = 0; k < 3; ++k) {
		std::cout << char('a' + i) << char('a' + j) << char('A' + k) << '=';
		std::cout << char('a' + i) << char('A' + k) << char('a' + j) << '\n';
	}
	o "DaA=aAD" e
	o "DbB=bBD" e
	o "DcC=cCD" e
	o "D=" e
	o "aT=TDa" e
	o "bT=TDb" e
	o "cT=TDc" e
	o "=(return)0" e
	return 0;	
}

I. Barbecue

徐神一波理性分析后发现在排除掉区间本身是回文串的情况后,剩下的只要根据区间长度的奇偶性即可得到胜负关系

然而徐神写了个Manacher判回文交上去结果WA了,后面在瞪了半天代码无果后我给徐神写了个Hash判回文,结果交上去过了没绷住

看来打印出来的板子也不可轻信的说

#include <bits/stdc++.h>

constexpr int $n = 1000005;

/*namespace manacher {

static char R[$n];

void odd(char *s, int n, std::function<void(int, int)> callback) {
	s[0] = 1; s[n + 1] = 0;
	for(int i = 1, m = 0, r = 0, k, l; i <= n; ++i) {
		if(i <= r) {
			k = m * 2 - i;
			if(i + R[k] <= r) {
				R[i] = R[k];
				callback(i - R[i] + 1, i + R[i] - 1);
				continue;
			}
		} else r = i;
		m = i, l = m * 2 - r;
		while(s[l] == s[r]) --l, ++r;
		R[i] = r - i; callback(l + 1, --r);
	}
}

void even(char *s, int n, std::function<void(int, int)> callback) {
	s[0] = 1; s[n + 1] = 0;
	for(int i = 1, m = 0, r = 0, k, l; i <= n; ++i) {
		if(i <= r) {
			k = m * 2 - i;
			if(i + R[k] <= r) {
				R[i] = R[k];
				if(R[i]) callback(i - R[i], i + R[i] - 1);
				continue;
			}
		} else r = i;
		m = i, l = m * 2 - r - 1;
		while(s[l] == s[r]) --l, ++r;
		R[i] = r - i; r -= 1; l += 1;
		if(r > l) callback(l, r);
	}
}

}*/

#define Tp template <typename T>
class FileInputOutput
{
    private:
        static const int S=1<<21;
        #define tc() (A==B&&(B=(A=Fin)+fread(Fin,1,S,stdin),A==B)?EOF:*A++)
        char Fin[S],*A,*B;
    public:
        Tp inline void read(T& x)
        {
            x=0; char ch; while (!isdigit(ch=tc()));
            while (x=(x<<3)+(x<<1)+(ch&15),isdigit(ch=tc()));
        }
        inline void read_char(char& ch)
        {
        	while (!isalpha(ch=tc()));
        }
        #undef tc
}F;

const int mod1=998244353,mod2=1e9+7;
struct Hasher
{
	int x,y;
	inline Hasher(const int& X=0,const int& Y=0)
	{
		x=X; y=Y;
	}
	friend inline bool operator == (const Hasher& A,const Hasher& B)
	{
		return A.x==B.x&&A.y==B.y;
	}
	friend inline Hasher operator + (const Hasher& A,const Hasher& B)
	{
		return Hasher((A.x+B.x)%mod1,(A.y+B.y)%mod2);
	}
	friend inline Hasher operator - (const Hasher& A,const Hasher& B)
	{
		return Hasher((A.x-B.x+mod1)%mod1,(A.y-B.y+mod2)%mod2);
	}
	friend inline Hasher operator * (const Hasher& A,const Hasher& B)
	{
		return Hasher(1LL*A.x*B.x%mod1,1LL*A.y*B.y%mod2);
	}
}H[$n],R[$n],pw[$n];
const Hasher seed=Hasher(31,131);

char s[$n];
int k[$n * 2];

inline Hasher getH(const int& l,const int& r)
{
	return H[r]-H[l-1]*pw[r-l+1];
}

inline Hasher getR(const int& l,const int& r)
{
	return R[l]-R[r+1]*pw[r-l+1];
}

int main() {
	int n, q; F.read(n); F.read(q);
	for (int i=1;i<=n;++i) F.read_char(s[i]);
	//manacher::odd (s, n, [](int l, int r) { if(r - l >= k[l + r]) k[l + r] = r - l; });
	//manacher::even(s, n, [](int l, int r) { if(r - l >= k[l + r]) k[l + r] = r - l; });
	pw[0]=Hasher(1,1); for (int i=1;i<=n;++i) pw[i]=pw[i-1]*seed;
	for (int i=1;i<=n;++i) H[i]=H[i-1]*seed+Hasher(s[i],s[i]);
	for (int i=n;i>=1;--i) R[i]=R[i+1]*seed+Hasher(s[i],s[i]);
	while(q--) {
		int l, r;
		F.read(l); F.read(r);
		if(getH(l,r)==getR(l,r)) std::puts("Budada"); else
		if((r - l) & 1)          std::puts("Budada"); else
		                         std::puts("Putata");
	}
	return 0;
}


J. Frog

祁神中后期写的奇妙几何+分类讨论题,由于我又没有看题目所以不好评价

#include<bits/stdc++.h>
using namespace std;
#define int long long

using LD = long double;
const LD PI = acos(-1.0L);
int t, ds, dt;

struct Pt{
	LD x, y;
	Pt operator*(const LD b)const{return Pt{x*b, y*b};}
	Pt operator+(const Pt &b)const{return Pt{x+b.x, y+b.y};}
	Pt operator-(const Pt &b)const{return Pt{x-b.x, y-b.y};}
	LD len2()const{return x*x+y*y;}
	LD len()const{return sqrtl(x*x+y*y);}	
	Pt rot()const{return Pt{-y, x};}	
};

void print(Pt b){
	cout << b.x << ' ' << b.y << '\n';
}

Pt getP(LD thi){
	return Pt{cosl(thi/180*PI), sinl(thi/180*PI)};	
}

Pt calc(Pt a, Pt b){
	LD len2 = (a-b).len2()*0.25L;
	Pt res1 = (a+b)*0.5L + (a-b).rot()*(sqrtl(1-len2)/(a-b).len());
	Pt res2 = (a+b)*0.5L + (b-a).rot()*(sqrtl(1-len2)/(a-b).len());
	return (res1.len() > res2.len() ? res1 : res2);
//	printf("a(%Lf %Lf) b(%Lf %Lf) res(%Lf %Lf)\n", a.x, a.y, b.x, b.y, res.x, res.y);
}

signed main(){
	ios::sync_with_stdio(0); cin.tie(0);
	cout << setiosflags(ios::fixed) << setprecision(12);
	cin >> t;
	while (t--){
		cin >> ds >> dt;
		Pt ps=getP(ds), pt=getP(dt);
		if (dt>ds && dt-ds>180) dt-=360;
		if (dt<ds && dt-ds<-180) dt+=360;
		
//		printf("ds=%lld dt=%lld\n", ds, dt);
		
		if (ds==dt){
			cout << "0\n";
			print(ps);
		}else if (abs(ds-dt)<=90){
			cout << "2\n";
			print(ps);
			print(calc(ps, pt));
			print(pt);
		}else if (abs(ds-dt)<=131){
			int dh;
			if (dt>ds) dh=ds+90;
			else dh=ds-90;
			Pt ph=getP(dh);
			Pt ph1=calc(ps, ph);
			Pt ph2=calc(ph1, pt);
			cout << "3\n";
			print(ps);
			print(ph1);
			print(ph2);
			print(pt);
		}else if (abs(ds-dt)<=180){
			int dh;
			if (dt>ds) dh=ds+90;
			else dh=ds-90;
			Pt ph=getP(dh);
			Pt ph1=calc(ps, ph);
			Pt ph2=calc(ph, pt);
			cout << "4\n";
			print(ps);
			print(ph1);
			print(ph);
			print(ph2);
			print(pt);
		}
	} 
	return 0;
}

K. Dynamic Reachability

刚开始没看到有向图以为是个傻逼题,后面观望了半天没人过又去读了遍题才发现我是瞎子,这下做不来一点了


L. Candy Machine

首先给\(\{a_n\}\)升序排序,考虑枚举最后\(>X\)的糖果中最小的那颗\(a_i\)

此时显然所有\(a_i\)之前的糖果都选上一定不会变劣,然后向后最多能选既可显然有二分性

#include<cstdio>
#include<iostream>
#include<algorithm>
#define int long long
#define RI register int
#define CI const int&
using namespace std;
const int N=1e6+5;
int n,a[N],pfx[N],ans;
signed main()
{
	RI i; for (scanf("%lld",&n),i=1;i<=n;++i) scanf("%lld",&a[i]);
	for (sort(a+1,a+n+1),i=1;i<=n;++i) pfx[i]=pfx[i-1]+a[i];
	for (i=1;i<=n;++i)
	{
		auto check=[&](CI l,CI r)
		{
			return pfx[r]<r*a[l];
		};
		int l=i,r=n,mid,ret=i-1; while (l<=r)
		if (check(i,mid=l+r>>1)) ret=mid,l=mid+1; else r=mid-1;
		ans=max(ans,ret-i+1);
	}
	return printf("%lld",ans),0;
}

M. BpbBppbpBB

祁神开场写的神秘模拟题,我题目都没看就不做评价

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

using pii = pair<int, int>;
#define ft first
#define sd second

const int N = 1005;
const int dir[4][2] = {{1, 0}, {-1, 0}, {0, 1}, {0, -1}};
int n, m;
char mp[N][N];
int tmp[6][6];
set<pii> st;


bool check(int x, int y){
	for (int i=0; i<6; ++i) for (int j=0; j<6; ++j){
		if (mp[x+i][y+j]=='.') tmp[i][j]=1;
		else tmp[i][j]=0;	
	}
	tmp[1][1]^=1;
	tmp[1][4]^=1;
	tmp[4][1]^=1;
	tmp[4][4]^=1;
	for (int i=0; i<6; ++i) tmp[i][0]^=1, tmp[i][5]^=1;
	for (int j=1; j<5; ++j) tmp[0][j]^=1, tmp[5][j]^=1;
//	printf("tmp:x=%d y=%d\n", x, y);
//	for (int i=0; i<4; ++i) for (int j=0; j<4; ++j){
//		printf("%d", tmp[i][j]);
//		if (j==3) puts("");
//	}
	bool ok=true;
	for (int i=0; i<6; ++i) for (int j=0; j<6; ++j){
		if (tmp[i][j]==0) ok=false;
	}
	return ok;
}

signed main(){
	scanf("%d%d", &n, &m);
	for (int i=1; i<=n; ++i){
		scanf("%s", mp[i]+1);	
	}
	for (int i=1; i<=n-5; ++i) for (int j=1; j<=m-5; ++j){
		if (check(i, j)) st.insert(make_pair(i, j));	
	}
	int ans1=0, ans2=st.size();
//	for (auto [x, y] : st) printf("(%d %d)\n", x, y);
	for (auto [x, y] : st){
		for (int i=0; i<4; ++i){
			if (st.count(make_pair(x+7*dir[i][0], y+7*dir[i][1]))){
				++ans1;
				break;
			}
		}
	}
	ans2-=ans1;
	ans1/=2;
	printf("%d %d\n", ans1, ans2);
	return 0;	
}

Postscript

感觉这场题都好神秘啊,一堆题我不知道题意但就是过了,这下混子闪总实锤了

posted @ 2024-04-05 19:27  空気力学の詩  阅读(114)  评论(0编辑  收藏  举报