标签:int res ll ans EdcationalRound62 dp mod
题目大意:
给你一个序列。有若干个位置没有填值.问你有多少种填值方案使得其不含任何长度大于等于3的回文串.
n
,
k
≤
1
e
5
n,k \leq 1e5
n,k≤1e5
题目思路:
容易发现就是要满足任何位置 a [ i ] ≠ a [ i + 2 ] a[i] \neq a[i+2] a[i]=a[i+2].那么对奇数和偶数位置分别求解相乘即可。
对于奇数位,问题转化为:有多少种填写方案使得其任何两个相邻的数不同.
可以看出这是一个经典问题。考虑分段+动态规划求解:
对于每一段连续的
−
1
-1
−1,两边的数会影响中间的结果。比如:
1 -1…-1 1 和 1 -1…-1 2
总体的,两边的数 a , b a,b a,b只会有两种情况: a = b a=b a=b和 a ≠ b a \neq b a=b.所以将状态升维做.(0代表不等)
a = b 时 , d p ( x , 1 ) = ( k − 1 ) ∗ d p ( x − 1 , 0 ) a = b 时,dp(x,1)=(k-1)*dp(x-1,0) a=b时,dp(x,1)=(k−1)∗dp(x−1,0)
a ≠ b 时 , d p ( x , 0 ) = ( k − 2 ) ∗ d p ( x − 1 , 0 ) + d p ( x − 1 , 1 ) a \neq b 时,dp(x,0)=(k-2)*dp(x-1,0)+dp(x-1,1) a=b时,dp(x,0)=(k−2)∗dp(x−1,0)+dp(x−1,1)
记忆化求解。
实现细节挺多
AC代码:
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define pii pair<int,int>
#define pb push_back
#define mp make_pair
#define vi vector<int>
#define vll vector<ll>
const int maxn = 1e6 + 5;
const int mod = 998244353;
int a[maxn] , b[maxn];
ll ksm (ll a , ll b){ ll ans = 1 , base = a;
while (b){if (b & 1) ans = ans * base % mod;b >>= 1;base = base * base % mod;}return ans;}
ll dp[maxn][2] , k;
ll dfs (ll x , ll t)
{
if (x <= 0) return t == 0;
ll &d = dp[x][t];
if (~d) return d;
//奇数
ll ans = 0;
if (t == 0) ans = ((k - 2) * dfs(x - 1 , 0)%mod + dfs(x - 1 , 1))%mod;
else ans = (k - 1) * dfs(x - 1 , 0)%mod;
return d = ans;
}
ll calc (int a[] , int n)
{
// 先还得判断原本有没有相等的
for (int i = 1 ; i < n ; i++){
if (a[i] == -1) continue;
if (a[i] == a[i + 1]) return 0;
}
ll ans = 1;
int l , r;l = 1 , r = 0;
for (int i = 1 ; i <= n + 1; i++){
ll res;
if (a[i] == -1) r++;
else {
// 连续-1区间为空,不进行计算
if (l > r) {
l = i + 1 , r = i;
continue;
}
// 特判区间在边界的
if (l == 1 || r == n){
// 区间为[1,n]的
if (l == 1 && r == n){
// 长度为1的
if (l == r) return k;
res = k * (k - 1)%mod * dfs(r - l - 1 , 0)%mod;
res = (res + k * dfs(r - l - 1 , 1)%mod)%mod;
}
else {
res = (k - 1) * dfs(r - l , 0)%mod;
res = (res + dfs(r - l , 1))%mod;
}
}
else
res = dfs(r - l + 1 , a[l - 1] == a[i]);
l = i + 1 , r = i;
ans = (ans * res) % mod;
}
}
return ans;
}
int main()
{
memset(dp , -1 , sizeof dp);
ios::sync_with_stdio(false);
int n; cin >> n >> k;
int x , y; x = y = 0;
for (int i = 1 ; i <= n ; i++){
int d ; cin >>d;
if (i & 1) a[++x] = d;
else b[++y] = d;
}
cout << calc(a , x) * calc(b , y) % mod << endl;
return 0;
}
标签:int,res,ll,ans,EdcationalRound62,dp,mod 来源: https://blog.csdn.net/qq_35577488/article/details/114385544
本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享; 2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关; 3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关; 4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除; 5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。