首页 > 其他分享 >题解:【ARC142D】 Deterministic Placing

题解:【ARC142D】 Deterministic Placing

时间:2023-06-07 16:26:02浏览次数:52  
标签:Placing int 题解 Deterministic 接好 箭尾 inline calc define

题目链接

大佬讲解的太精简了,做点蒟蒻视角的思考补充。下面记摆放棋子的点为黑点,没有摆放棋子的为白点。

因为进行无数次操作后,占据节点集合总是唯一,所以黑点一定是在反复横跳;每个位置上只能存在一个黑点,所以每次把移动黑点经过的边拿出来,得到的是若干条不相交的链,并且这些链一定可以将整棵树填满。转化问题变成求链的划分方案。

但是问题在于多种链的划分可能对应同一种摆放方式,我们最后要求的是有多少种摆放方式,所以需要接着转化问题。注意到如果将点而不是边视为链结构的话,那么这个结构即为一个白点后面跟一串黑点,于是便得到了抽象的模型:将白点视为箭头,黑点视为箭身和箭尾,于是得到了若干个 \(\rightarrow\)。那么每次操作可以抽象成所有点向着箭头方向走一步,然后将箭头翻转过来。

有了模型就可以考虑如何计数了,直接记 \(f_{i,0 \sim 7}\) 表示当前节点状态。

  1. 箭身,前面没接,后面没接。
  2. 箭身,前面接了,后面没接。
  3. 箭身,前面没接,后面接了。
  4. 箭身,前面接了,后面接了。
  5. 箭头,后面没接。
  6. 箭头,后面接了。
  7. 箭尾,前面没接。
  8. 箭尾,前面接了。

边界状态是 \(f_{i,0/4/6} = 1\),因为一个节点初始可以作为任意一部分。

考虑不合法的拼接状态:

  • 箭尾不能和箭尾相连。否则两条链可以直接视为一条链。
  • 箭头不能和箭头相连。因为操作一次后反转箭头,箭头变成箭尾就等价于上面那种不合法状态。
  • 箭身只能和箭身相连。如果和箭尾相连,那么从当前位置揭开,后面的箭身可以跟着另一条链走;箭头则是一样的,仍然是操作一次翻转变成箭尾,等价于前者的不合法情况。

dfs 遍历整棵树,需要一个中转数组暂时记录答案。根据儿子是什么状态来转移到自己是什么状态,同时刨除掉不合法的情况:

  1. 只能跟都接好了的箭身。
  2. 可以跟都接好了的箭身。也可以跟什么都没接的箭身,要让它变成前面接了的箭身,可以跟后面没接好的箭头,也可以接着跟前面接好的箭身。
  3. 可以跟都接好了的箭身。也可以跟什么都没接的箭身,要让它变成后面接了的箭尾,可以跟前面没接好的箭尾,也可以接着跟后面接好的箭身。
  4. 可以跟都接好了的箭身。可以从前面接好后面没接好的箭身转移而来,要让它变成都接好的箭身,这样后面可以跟前面没接好后面接好的箭身,也可以跟前面没接好的箭尾。可以从后面接好前面没接好的箭身转移而来,要让它变成前后都接好的箭身,这样后面可以跟后面没接好前面接好的箭身,也可以跟后面没接好的箭头。
  5. 只能跟钦定好了的接好前头的箭尾。
  6. 可以跟钦定好了的接好前头的箭尾。也可以从当前是后面没接的箭头转移过来,后面就可以跟接好后面没接前面的箭身,或者没接前面的箭尾。
  7. 只能跟接好了的箭头。
  8. 可以跟接好了的箭头。也可以从当前是前面没接的箭尾转移过来,后面就可以跟接好前面了的箭身,或者还没接好后面的箭头。

最后答案即为 \(f_{root,3} + f_{root,5} + f_{root,7}\),复杂度 \(\mathcal O(n)\),带一个奇大无比的转移常数。

#include<bits/stdc++.h>
#define ld long double
#define ui unsigned int
#define ull unsigned long long
#define int long long
#define eb emplace_back
#define pb pop_back
#define ins insert
#define mp make_pair
#define pii pair<int,int>
#define fi first
#define se second
#define power(x) ((x)*(x))
#define gcd(x,y) (__gcd((x),(y)))
#define lcm(x,y) ((x)*(y)/gcd((x),(y)))
#define lg(x,y)  (__lg((x),(y)))
using namespace std;

namespace FastIO
{
	template<typename T=int> inline T read()
	{
	    T s=0,w=1; char c=getchar();
	    while(!isdigit(c)) {if(c=='-') w=-1; c=getchar();}
	    while(isdigit(c)) s=(s<<1)+(s<<3)+(c^48),c=getchar();
	    return s*w;
	}
	template<typename T> inline void read(T &s)
	{
		s=0; int w=1; char c=getchar();
		while(!isdigit(c)) {if(c=='-') w=-1; c=getchar();}
	    while(isdigit(c)) s=(s<<1)+(s<<3)+(c^48),c=getchar();
	    s=s*w;
	}
	template<typename T,typename... Args> inline void read(T &x,Args &...args)
	{
		read(x),read(args...);
	}
	template<typename T> inline void write(T x,char ch)
	{
	    if(x<0) x=-x,putchar('-');
	    static char stk[25]; int top=0;
	    do {stk[top++]=x%10+'0',x/=10;} while(x);
	    while(top) putchar(stk[--top]);
	    putchar(ch);
	    return;
	}
}
using namespace FastIO;

namespace MTool
{	
    #define TA template<typename T,typename... Args>
    #define TT template<typename T>
    TT inline void Swp(T &a,T &b) {T t=a;a=b;b=t;}
    TT inline void cmax(T &a,T b) {a=a>b?a:b;}
    TT inline void cmin(T &a,T b) {a=a<b?a:b;}
    struct ModNum
	{
		struct fastmod
		{
		    using u128=__uint128_t; using u64=uint64_t; using u32=signed;
		    u32 f,l; u64 m,d;
		    fastmod(u64 D=998244353):d(D) 
		    {
		        const u128 ONE=1;
		        l=64-__builtin_clzll(d-1);
		        u128 M=((ONE<<(64+l))+(ONE<<l))/d;
		        if(M<(ONE<<64)) f=1,m=M; else f=0,m=M-(ONE<<64);
		    }
		    inline friend u64 operator / (u64 x,const fastmod &y)
		    {
		        if(y.f) return u128(x)*y.m>>64>>y.l;
		        else return (((x-(u128(x)*y.m>>64))>>1)+(u128(x)*y.m>>64))>>(y.l-1);
		    }
		    inline friend u64 operator % (u64 x,const fastmod &y)
		    {
		        return x-x/y*y.d;
		    }
		    inline friend u64 operator + (u64 x,const fastmod &y) {return x+y.d;}
		    inline friend u64 operator - (u64 x,const fastmod &y) {return x-y.d;}
		    inline friend bool operator == (u64 x,const fastmod &y) {return x==y.d;}
		    inline friend bool operator >  (u64 x,const fastmod &y) {return x>y.d;}
		    inline friend bool operator <  (u64 x,const fastmod &y) {return x<y.d;}
		    inline friend bool operator >= (u64 x,const fastmod &y) {return x>y.d||x==y.d;}
		    inline friend bool operator <= (u64 x,const fastmod &y) {return x<y.d||x==y.d;}
		};
		fastmod Mod;
		inline void ChangeMod(int MOD){Mod=MOD;}
		TT inline void Madd(T &a,T b) {a=a+b>Mod?a+b-Mod:a+b;}
		TT inline void Mdel(T &a,T b) {a=a-b<0?a-b+Mod:a-b;}
		TT inline void Mmul(T &a,T b) {a=a*b%Mod;}
		TT inline void Mmod(T a) {a=(a%Mod+Mod)%Mod;}
		TT inline T Cadd(T a,T b) {return a+b>=Mod?a+b-Mod:a+b;}
		TT inline T Cdel(T a,T b) {return a-b<0?a-b+Mod:a-b;}
		TT inline T Cmul(T a,T b) {return a*b%Mod;}
		TT inline T Cmod(T a) {return (a%Mod+Mod)%Mod;}
		TA inline void Madd(T &a,T b,Args... args) {Madd(a,Cadd(b,args...));}
		TA inline void Mdel(T &a,T b,Args... args) {Mdel(a,Cadd(b,args...));}
		TA inline void Mmul(T &a,T b,Args... args) {Mmul(a,Cmul(b,args...));}
		TA inline T Cadd(T a,T b,Args... args) {return Cadd(Cadd(a,b),args...);}
		TA inline T Cdel(T a,T b,Args... args) {return Cdel(Cdel(a,b),args...);}
		TA inline T Cmul(T a,T b,Args... args) {return Cmul(Cmul(a,b),args...);}
		TT inline T qpow(T a,T b) {int res=1; while(b) {if(b&1) Mmul(res,a); Mmul(a,a); b>>=1;} return res;}
		TT inline T qmul(T a,T b) {int res=0; while(b) {if(b&1) Madd(res,a); Madd(a,a); b>>=1;} return res;}
		TT inline T spow(T a,T b) {int res=1; while(b) {if(b&1) res=qmul(res,a); a=qmul(a,a); b>>=1;} return res;}
		private:TT inline void exgcd(T A,T B,T &X,T &Y) {if(!B) return X=1,Y=0,void(); exgcd(B,A%B,Y,X),Y-=X*(A/B);}
		public:TT inline T Ginv(T x) {T A=0,B=0; exgcd(x,Mod,A,B); return Cmod(A);}
		#undef TT
		#undef TA
	};
}
using namespace MTool;

inline void file()
{
    freopen(".in","r",stdin);
    freopen(".out","w",stdout);
    return;
}

bool Mbe;

namespace LgxTpre
{
    static const int MAX=100010;
    static const int inf=2147483647;
    static const int INF=4557430888798830399;
    static const int mod=1e9+7;
    static const int bas=131;
    
	ModNum M;
	int n,x,y;
	vector<int> G[MAX];
	
	int f[MAX][8],g[8],u,v;
	inline void calc(int x,int y,int z) {M.Madd(g[x],M.Cmul(f[u][y],f[v][z]));}
	void dfs(int now,int father)
	{
		f[now][0]=f[now][4]=f[now][6]=1;
		for(auto to:G[now]) if(to!=father)
		{
			dfs(to,now),u=now,v=to;
			memset(g,0,sizeof g);
			calc(0,0,3);
			calc(1,1,3),calc(1,0,4),calc(1,0,1);
			calc(2,2,3),calc(2,0,6),calc(2,0,2);
			calc(3,3,3),calc(3,2,4),calc(3,1,6),calc(3,1,2),calc(3,2,1);
			calc(4,4,7);
			calc(5,5,7),calc(5,4,2),calc(5,4,6);
			calc(6,6,5);
			calc(7,7,5),calc(7,6,1),calc(7,6,4);
			memcpy(f[now],g,sizeof f[now]);
		}
	}
	
    inline void lmy_forever()
    {
    	M.ChangeMod(998244353);
    	read(n);
    	for(int i=1;i<n;++i) read(x,y),G[x].eb(y),G[y].eb(x);
    	dfs(1,0);
    	write(M.Cadd(f[1][3],f[1][5],f[1][7]),'\n');
    	return;
    }
}

bool Med;

signed main()
{
//  file();
    fprintf(stderr,"%.3lf MB\n",abs(&Med-&Mbe)/1048576.0);
    int Tbe=clock();
    LgxTpre::lmy_forever();
    int Ted=clock();
    cerr<<1e3*(Ted-Tbe)/CLOCKS_PER_SEC<<" ms\n";
    return (0-0);
}

标签:Placing,int,题解,Deterministic,接好,箭尾,inline,calc,define
From: https://www.cnblogs.com/LittleTwoawa/p/17463523.html

相关文章

  • ABC300F 题解
    前两天忘发出来了,补一下QAQ题目链接题意简述给定一个长度为\(n\)且只包含\(\texttt{o}\)和\(\texttt{x}\)的字符串\(s\)以及正整数\(n\)\(m\)\(k\),令字符串\(T=s^{m}\),求将\(T\)中的\(k\)个\(\texttt{x}\)变成\(\texttt{o}\)之后,\(T\)中连续\(\texttt{o}......
  • P3392 涂国旗 题解
    题目大意题目真的是不说人话......有一个国家的国旗是由一个N*M的方格组成的。如果想要这面国旗合法,就必须满足要求:国旗从上到下必须是白色、蓝色和红色,顺序不能改变。每一种颜色都至少有一行。小a这时候捡到了一块破布,希望你通过涂颜色的方式,把破布成合法的国旗,并且要......
  • 题解 P4556 [Vani有约会]雨天的尾巴 /【模板】线段树合并
    传送门如题目所言,这就是个线段树合并的板子题。题目大意题目描述首先村落里的一共有\(n\)座房屋,并形成一个树状结构。然后救济粮分\(m\)次发放,每次选择两个房屋\((x,y)\),然后对于\(x\)到\(y\)的路径上(含\(x\)和\(y\))每座房子里发放一袋\(z\)类型的救济粮。然......
  • 【每日一题】LeetCode 786. 第K个最小的素数分数(待补全题解思路)
    题目给你一个按递增顺序排序的数组arr和一个整数k。数组arr由1和若干素数组成,且其中所有整数互不相同。对于每对满足0<i<j<arr.length的i和j,可以得到分数arr[i]/arr[j]。那么第k个最小的分数是多少呢?以长度为2的整数数组返回你的答案,这里answer......
  • 2023上半年(下午)网络工程师试题解析
    2023上半年(下午)网络工程师试题解析试题一(20分)某企业办公楼网络拓扑如图1-1所示。该网络中交换机Switch1-Switch4均是二层设备,分布在办公楼的各层,上联采用千兆光纤。核心交换机、防火墙、服务器部署在数据机房,其中核心交换机实现冗余配置。图1-1问题1(4分)该企业办公网络采用172.16.1......
  • CF1559D2 Mocha and Diana (Hard Version) 题解
    Luogu|Codeforces题意给定两个森林\(A\)和\(B\),均有编号\(1\)到\(n\)的节点,边数分别为\(m_1,m_2\)。现在进行加边操作,但是有两个要求:如果在第一个森林加一条\((u,v)\)的边,第二个森林也要进行同样的操作。反之同理。加边后两个森林依旧是森林。一棵树也是森林。......
  • ERROR 1418 (HY000) at line 1323: This function has none of DETERMINISTIC, NO SQL
    ERROR1418(HY000)atline1323:ThisfunctionhasnoneofDETERMINISTIC,NOSQL,orREADSSQLDATAinitsdeclarationandbinaryloggingisenabled(you*might*wanttousethelesssafelog_bin_trust_function_creatorsvariable) 开启了bin-log,我们就必须指定......
  • 应用问题解决-分布式锁(LUA保证删除原子性)
    问题:删除操作缺乏原子性场景1、index1获得锁、执行具体操作、比较lock的uuid值确实和自己生成的uuid是否相等,相等则删除锁。uuid=v1set(lock,uuid)uuid.equals(get("lock"))2、但是index1执行删除前,lock刚好过期时间已经到了,被redis自动释放3、此时index2获取锁,执行具体......
  • 在centos7升级nodejs存在的无法切换版本的问题解决
    1.安装n管理工具npminstall-gn安装最新版本nlatest安装指定版本 n8.11.3 2.切换nodejs版本n选择已安装的版本 ο node/8.11.3  node/10.4.1查看当前版本node-v,下面表示已切换成功v8.13.3但问题来了,切换后,查看版本还是原来的v6.13.3,看下面 使用n切换nodejs......
  • 应用问题解决——缓存穿透、缓存击穿、缓存雪崩
    一、缓存穿透缓存穿透:key对应的数据在数据源并不存在,每次针对key的请求从缓存中获取不到,请求都会压到数据源,从而可能压垮数据源,比如用一个不存在的用户id获取用户信息,不论缓存还是数据库都没有,若黑客利用此漏洞进行攻击可能压垮数据库现象:1、应用服务器压力变大2、redis命中率......