codeforces 1140E Palindrome-less Arrays

题目链接:http://codeforces.com/contest/1140/problem/E

题目大意:

如果一个数组的存在一个奇数长的回文就不好。

不是不好的数组是好的。

你可以把-1用1到k中一个数替换。问可以有多少种不同的好数组。

开虚拟赛最后一分钟把它A了,很开心,很开心。

思路:

我们翻译一下,如果存在长度为5的回文就必须会出现长度为3的回文。

也就是说不能出现长度为3回文。

也就是说x[i]!=x[i+2],x[i]!=x[i-2];(x[i]为输入数组)

那我们把数组分为两个数组,按奇偶分。(1,3,5,,,)(2,4,6,,,)

这两个数组就都要满足一个条件x[i]!=x[1+i]&&x[i]!=x[i-1];(相邻两个数不能相等)

然后我们就开始DP啦。

对于奇偶两个数组我就分析一个啦,因为都差不多。(相邻两个数不能相等)

首先,当然是n*k的DP。

DP[a][b]表示到a下为b的方案数。

所以DP[a][b]等于所有DP[a-1][i](1<=i<=k,i!=b)的和。

如果x[a]为-1,就算所有的1到k。

如果x[a]>0,就只算DP[a][x[a]];

这个可以理解吗?

可以理解就太好了!!!

然而,你在DP的过程中,发现DP[a][i](1<=i<=k)中只可能有两个不同的值(不会超过3个),而且产生不同的值是一个特殊的位置。

你可以先拿小一点的数据打表看看。

也就是说,对于每一个状态。只有两种可能,而不是k种可能。

所以,我们就可以写O(n)的DP了。

我画了两张图给你们看看。

然后到了愉快的贴代码时间了。不是很懂可以私聊QQ:1328247116,也可以下面留言。~~

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

#define int long long
#define IOS ios::sync_with_stdio(false);
#define endl "\n"
#define MAX 200050
#define mod 998244353

///
int x[MAX];
int dp[MAX];
int dp_1=1,dp_1_sum=1;
int dp_2=1,dp_2_sum=1;
int ans[MAX];
///
signed main()
{
    IOS;

    int n,m;
    cin>>n>>m;
    for(int i=1;i<=n;i++){
        cin>>x[i];
    }

    if(x[1]>0){
        dp[1]=0;
        dp_1=x[1],dp_1_sum=1;
    }
    else{
        dp[1]=1;
        dp_1=1,dp_1_sum=1;
    }

    for(int i=3;i<=n;i+=2){
        if(x[i]>0){
            if(x[i]==dp_1){
                dp_1_sum=(m-1)*dp[i-2]%mod;
            }
            else{
                dp_1_sum=((m-2)*dp[i-2]%mod+dp_1_sum)%mod;
            }
            dp_1=x[i];
        }
        else{
            dp[i]=((m-2)*dp[i-2]%mod+dp_1_sum)%mod;
            dp_1_sum=(m-1)*dp[i-2]%mod;
        }
    }

    ///
    if(x[2]>0){
        dp[2]=0;
        dp_2=x[2],dp_2_sum=1;
    }
    else{
        dp[2]=1;
        dp_2=1,dp_2_sum=1;
    }

    for(int i=4;i<=n;i+=2){
        if(x[i]>0){
            if(x[i]==dp_2){
                dp_2_sum=(m-1)*dp[i-2]%mod;
            }
            else{
                dp_2_sum=((m-2)*dp[i-2]%mod+dp_2_sum)%mod;
            }
            dp_2=x[i];
        }
        else{
            dp[i]=((m-2)*dp[i-2]%mod+dp_2_sum)%mod;
            dp_2_sum=(m-1)*dp[i-2]%mod;
        }
    }
    int ans;
    if(n%2==0){
        ans=(dp_1_sum+(m-1)*dp[n-1]%mod)*(dp_2_sum+(m-1)*dp[n]%mod)%mod;
    }
    else{
        ans=(dp_1_sum+(m-1)*dp[n]%mod)*(dp_2_sum+(m-1)*dp[n-1]%mod)%mod;
    }
    cout<<ans;
    return 0;
}

/*

*/

原文地址:https://www.cnblogs.com/opooopooo/p/10620960.html

时间: 2024-07-31 09:43:06

codeforces 1140E Palindrome-less Arrays的相关文章

Codeforces 486C Palindrome Transformation(贪心)

题目链接:Codeforces 486C Palindrome Transformation 题目大意:给定一个字符串,长度N,指针位置P,问说最少花多少步将字符串变成回文串. 解题思路:其实只要是对称位置不相同的,那么指针肯定要先移动到这里,修改字符只需要考虑两种方向哪种更优即 可.然后将所有需要到达的位置跳出来,贪心处理. #include <cstdio> #include <cstring> #include <cstdlib> #include <vec

Codeforces 309C Memory for Arrays 二进制模拟进位

题目链接:点击打开链接 题意: 给定n个箱子m个物品 下面n个数字表示箱子的容量 下面m个数字b1-bm 表示物品体积为2^bi大 问最多有多少个物品可以放入箱子. 思路: 贪心,先放小的,小的不能放再放大的 显然我们把n个箱子拆成二进制,然后模拟二进制减法运算. 剩下就是简单模拟 #include<stdio.h> #include<string.h> #include<iostream> #include<algorithm> #include<m

Codeforces 159D Palindrome pairs

http://codeforces.com/problemset/problem/159/D 题目大意: 给出一个字符串,求取这个字符串中互相不覆盖的两个回文子串的对数. 思路:num[i]代表左端点在i这个位置的回文串个数,然后用树状数组维护sum[i],代表回文串右端点小于等于i的回文串数,总复杂度:O(n^2) 1 #include<cstdio> 2 #include<cmath> 3 #include<algorithm> 4 #include<cstr

Codeforces 932G Palindrome Partition - 回文树 - 动态规划

题目传送门 通往???的传送点 通往神秘地带的传送点 通往未知地带的传送点 题目大意 给定一个串$s$,要求将$s$划分为$t_{1}t_{2}\cdots t_{k}$,其中$2\mid k$,且$t_{i} = t_{k - i}$,问方案数. 直接做不太好做.虽然可以$O(n^{2})$进行动态规划. 考虑做一步转化:设$s' = s_{1}s_{n}s_{2}s_{n - 1}\cdots s_{n / 2}s_{n / 2 + 1}$. 然后它的一个偶回文划分可以和原来的划分一一对应.

CodeForces 486C Palindrome Transformation

题意: n(10^5)个字符  光标停在第pos个字符上  光标可以左右任意移动  而且可以从最左移到最右也可以从最右移到最左  在光标处的字符可以按字母顺序或倒序更改  更改也可以a->z或者z->a  光标移动和字符更改都需要1s  问最短几s能把串变成回文的 思路: 最后的状态是一定的  因此更改的次数和策略无关  扫一遍就可以知道更改最少需要几s 光标移动需要一定的策略  容易想到最优的方法一定是在字符串的一半移动  因此记录在字符串左一半和右一半最远的不回文的位置  让光标移动就好了

CodeForces 7D Palindrome Degree

字符串hash.首先说下需要注意的地方:当对Mod取余时,可能造成本不相同的,取余结束之后相同了. 此时应对多个不同的Mod取余,多次计算只能说降低上述情况的发生.感觉正式比赛中不会有这种题,比较拼RP. 比如此题,Mod = 2^32,可以,Mod = 2^64,WA了... #include <algorithm> #include <iostream> #include <cstring> #include <cstdlib> #include <

CodeForces 7D Palindrome Degree 字符串hash

题目链接:点击打开链接 #include<stdio.h> #include<iostream> #include<string.h> #include<set> #include<vector> #include<map> #include<math.h> #include<queue> #include<string> #include<stdlib.h> #include<a

codeforces 1045I Palindrome Pairs 【stl+构造】

题目:戳这里 题意:给1e5个字符串,问有多少对字符串组合,满足最多只有一种字符有奇数个. 解题思路:每种情况用map存一下就行了.感觉这题自己的代码思路比较清晰,所以写个题解记录一下 附ac代码: 1 #include <bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 const int maxn = 2e5 + 10; 5 const ll mod = 998244353; 6 int arr[33]; 7 i

6月好题记录

Codeforces 1166C A Tale of Two Lands [绝对值问题]给定一个数列,求其中满足\(min{|x+y|,|x-y|} \leq min{|x|,|y|}\)且\(max{|x|,|y|} \leq max{|x+y|,|x-y|}\)的数对\((x,y)\)个数. \(x,y\)的符号都需要分类讨论,好像有点复杂.事后明白了符号在这道题里是不影响的. 我们可以这样来考虑.对于两个正数\(x,y(x<y)\),如果仅改变符号不会影响\(|x+y|\)和\(|x-y|