把博客园图标替换成自己的图标
把博客园图标替换成自己的图标end

题解 [ABC256G] Black and White Stones

洛谷

题意

有一个 n 边形,每条边上有 d+1 个石子,相邻两边公用一个石子。石子有白色或者黑色。问一共有多少种方案使得所有边上的白色石子数量相同。对 998244353 取模。

n1012d104

分析

首先对于环形的题目,我们可以想到一个重要技巧:拆环成链。我们将 n 边形切换成 n 条相连的边。

很显然,我们第一个需要满足的条件即是我们的首石子与末石子颜色需要相同,其次为每条边的白色石子个数相同。

对于我们的第二个条件,我们可以枚举我们每条边的白色石子个数。

我们设计一个状态:fi,0/1,0/1,表示在取了第 i 条边后,首石子的颜色为 0/1,末石子的颜色为 0/1,(0 为黑色)。

那么我们对这个状态进行转移,令枚举的白色石子的数量为 x
fi,0,0=fi1,0,1×Cd1x1+fi1,0,0×Cd1x
fi,0,1=fi1,0,1×Cd1x2+fi1,0,0×Cd1x1
fi,1,0=fi1,1,0×Cd1x+fi1,1,1×Cd1x1
fi,1,1=fi1,1,0×Cd1x1+fi1,1,1×Cd1x2

由此,我们就可以写出我们的暴力:

dp[0][0][0]=dp[0][1][1]=1;
for(int i=1; i<=n; i++) {
dp[i][0][0]=(dp[i-1][0][1]*C(d-1,x-1)%mod+dp[i-1][0][0]*C(d-1,x) %mod)%mod;
dp[i][0][1]=(dp[i-1][0][1]*C(d-1,x-2)%mod+dp[i-1][0][0]*C(d-1,x-1)%mod)%mod;
dp[i][1][0]=(dp[i-1][1][0]*C(d-1,x) %mod+dp[i-1][1][1]*C(d-1,x-1)%mod)%mod;
dp[i][1][1]=(dp[i-1][1][0]*C(d-1,x-1)%mod+dp[i-1][1][1]*C(d-1,x-2)%mod)%mod;
}
ans=(ans+dp[n][0][0]+dp[n][1][1])%mod);

时间复杂度:O(n)

正解

我们可以发现,我们对于枚举的这个数量下,我们转移的几个参数都是相同的。

也就是说,我们每添加一条边的转移都是相同的,再加上我们的 n1014,这让我们想到,我们是否可以使用矩阵快速幂来解决。

inline int solve(int X) {
init(X);//预处理ans与bas
int cnt=n;
while(cnt) {
if(cnt&1) ans=ans*bas;
bas=bas*bas;
cnt>>=1;
}
return (ans.a[1][1]+ans.a[1][4])%MOD;
}

对于我们的排列组合的处理,我们可以以 O(d) 的复杂度预处理,或者预处理阶乘与其逆元。

整体的复杂度为:O(logn)

总结一下,我们此题运用了 DP,与矩阵的快速幂的优化。

posted @   djh0314  阅读(12)  评论(0编辑  收藏  举报  
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
浏览器标题切换
浏览器标题切换end
点击右上角即可分享
微信分享提示