• nikkei2019_2_qual_f Mirror Frame


    nikkei2019_2_qual_f Mirror Frame

    https://atcoder.jp/contests/nikkei2019-2-qual/tasks/nikkei2019_2_qual_f

    在二维平面内,有一个正方形区域,顶点分别为 ((0,0),(0,N),(N,0),(N,N)) .

    光线可以在这个区域内反射,且满足入射角等于出射角.

    对于严格在区域内的点 ((x,y),0 < x < N, 0 < y < N) ,定义它的路径为

    • ((x,y)) 出发,向 ((x+1,y+1),(x-1,y-1),(x+1,y-1),(x-1,y+1)) 射出的四条光线的路径的并集

    对于每个严格在区域内的位置,存在一个灯泡,初始状态为打开或者关闭.

    每次可以选择一个严格在区域内的点,然后翻转所有在它的路径上的灯泡的状态.

    现在有一些灯泡的初始状态还未确定,问有多少种确定这些灯泡的方案,满足最后存在一种操作序列使得所有灯泡关闭.

    答案对 (998244353) 取模

    (2 le N le 1500)

    Tutorial

    考虑如何判断一种状态是否合法

    首先,沿对角线对称的灯泡的状态一定要相等.

    一个灯泡的路径上所有的灯的坐标的 (x+y) 奇偶性相等,所以将按 (x+y) 分类考虑

    现在问题可以转化为

    (n) 个点的完全图,每条边有边权 (0)(1) .每次可以选择两个点,并翻转所有至少和这两个点中的一个相邻的边的状态.

    问是否可以将所有边的边权变为 (0)

    如果我们找到一个回路 ((x_1,x_2,cdots,x_k=x_1)) ,并依次翻转 ((x_1,x_2),(x_2,x_3),cdots,(x_{k-1},x_k)) ,那么状态改变的边就是 ((x_1,x_2),(x_2,x_3),cdots,(x_{k-1},x_k)) .也就是说,存在合法方案的充分条件为图中的 (1) 边存在欧拉回路.

    假如 (n) 为偶数,那么如果我们翻转两个点 ((a,b)) ,那么 (a,b) 相邻的 (1) 边度数的奇偶性发生变化,所以可以通过操作使得所有点的度数为偶数.所以当 (n) 为偶数的时候一定合法.

    假如 (n) 为奇数,那么翻转两个点 ((a,b)) 时, (a,b) 的度数奇偶性不会发生变化(同时证明了必要性),所以必须要满足每个点的相邻的 (1) 边数为偶数.

    考虑求方案

    (n) 个点((n) 为奇数)的完全图,每条边的边权 (0)(1)(-1), 对于所有的 (-1) 边分配 (0)(1) 的边权,使得所有点相邻的 (1) 边数为偶数

    对于每个 (-1) 边联通块, (1) 边度数为奇数的点必须是偶数个,否则无解.

    方案数就是 (-1) 边数减去树边个数((n) 减去联通块个数)

    Code

    #include <cmath> 
    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <vector>
    #define debug(...) fprintf(stderr,__VA_ARGS__)
    using namespace std;
    template<class T> void rd(T &x) {
    	x=0; int f=1,ch=getchar();
    	while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    	while(ch>='0'&&ch<='9'){x=x*10-'0'+ch;ch=getchar();}
    	x*=f;
    }
    typedef long long ll;
    const int mod=998244353;
    const int maxn=1500+5;
    int n; char A[maxn][maxn];
    int head[maxn];
    int adj[maxn][maxn],deg[maxn];
    int vis[maxn],E,P,C;
    struct edge {
    	int to,nex;
    	edge(int to=0,int nex=0):to(to),nex(nex){}
    };
    vector<edge> G;
    inline int add(int x) {return x>=mod?x-mod:x;}
    ll power(ll x,ll y) {
    	ll re=1;
    	while(y) {
    		if(y&1) re=re*x%mod;
    		x=x*x%mod;
    		y>>=1;
    	}
    	return re;
    }
    inline void addedge(int u,int v) {
    	G.push_back(edge(v,head[u])),head[u]=G.size()-1;
    	G.push_back(edge(u,head[v])),head[v]=G.size()-1;
    }
    inline int idx0(int x,int y) {return x+y;}
    inline int idx1(int x,int y) {return x<y?idx0(0,y-x):idx0(x-y,0);}
    inline bool upd(int x,int y,char c) {
    	if(c=='?') return 1;
    	int a=x+y,b=x-y;
    	if(a>n) a=2*n-a;
    	if(b<0) b=-b;
    	x=(a+b)/2,y=a-x;
    	a=idx0(x,y),b=idx1(x,y);
    	if(a>b) swap(a,b);
    	if(adj[a][b]==-1) {
    		adj[a][b]=c=='x'; 
    		deg[a]^=adj[a][b];
    		deg[b]^=adj[a][b];
    	}
    	else return adj[a][b]==(c=='x');
    	return 1;
    }
    void travel(int u) {
    	if(vis[u]) return; vis[u]=1;
    	++P; if(deg[u]) ++C;
    	for(int i=head[u];~i;i=G[i].nex) {
    		int v=G[i].to;
    		++E;
    		travel(v);
    	}
    }
    int sol(int k) {
    	for(int i=1;i<n;++i) for(int j=1;j<n;++j) if(((i+j)&1)==k) {
    		if(!upd(i,j,A[i][j])) return 0;
    	}
    	int cnt=0;
    	for(int i=k;i<=n;i+=2) ++cnt;
    	if(~cnt&1) {
    		int an=1;
    		for(int i=k;i<=n;i+=2) for(int j=i+2;j<=n;j+=2) {
    			if(adj[i][j]==-1) an=add(an<<1);
    		}
    		return an;
    	}
    	for(int i=k;i<=n;i+=2) for(int j=i+2;j<=n;j+=2) {
    		if(adj[i][j]==-1) addedge(i,j);
    	}
    	int an=1;
    	for(int i=k;i<=n;i+=2) if(!vis[i]) {
    		E=0,P=0,C=0,travel(i),E>>=1;
    		if(C&1) return 0;
    		an=an*power(2,E-(P-1))%mod;
    	}
    	return an;
    }
    int main() {
    	rd(n);
    	for(int i=1;i<n;++i) scanf("%s",A[i]+1);
    	memset(adj,-1,sizeof(adj));
    	memset(head,-1,sizeof(head));
    	printf("%lld
    ",(ll)sol(0)*sol(1)%mod);
    	return 0;
    }
    
  • 相关阅读:
    专题一 Java基础语法
    IOC属于那种设计模式?
    java桌面应用开发
    Gitblit
    基于JSoup库的java爬虫开发学习——小步快跑
    tomcat和solr的整合——小步快跑
    SSM mapper文件SQL语句里面的 小于号 Tag name expected 无法识别解读
    Java从FTP服务器中获取PDF文件数据
    idea 控制台log日志中文乱码解决方案
    Java开发文档Swagger的使用详细教程
  • 原文地址:https://www.cnblogs.com/ljzalc1022/p/13266208.html
Copyright © 2020-2023  润新知