Atcoder AGC031B Reversi (DP计数)

简单的计数题。(总算做出一道AGC的B题了,然而这场比赛我忘记打了233333)

题目链接: https://atcoder.jp/contests/agc031/tasks/agc031_b

题意: 有一个长度为\(N\)的颜色序列,第\(i\)个位置初始颜色为\(a_i\), 可以执行若干次操作,每次可以选择两个颜色一样的位置,然后把这两个位置中间的区间都刷成和两端相同的颜色,问最后本质不同的序列有多少种。

题解: 最重要的想法就是要深刻地理解本质不同。

因为我们不论如何操作,最后得到的序列一样就算一样,所以假设\([l_1,r_1]\)和\([l_2,r_2]\)分别是先后两次操作。

若前者和后者相交但不包含,若前后两次刷成的颜色相同,我们可以等效成一次操作,操作区间为它们的并。(等效法?文化课走火入魔了吧)若前后两次颜色不同,那么这种情况一定是不存在的,因为相交但不包含意味着第一个区间的一个端点在第二个区间里,那这个端点在执行完前面的操作之后就不再是颜色2而变成颜色1了。

若前者包含后者,则后者无用。

若后者包含前者,则前者无用。

若两次区间不相交,则两次都有用。

所以本题就是要求把长度为\(N\)的序列内取出若干不相交区间,每个区间两端点颜色相同的方案数。

我们先对序列进行如下处理: 把所有连续的颜色相同的区间缩成一个位置。例如122333441变成12341.

然后\(f_i\)表示前\(i\)个的方案数。

\(f_i=\sum_{j<i, a_j=a_i} f_{j-1}\)

桶优化。

时间复杂度\(O(n)\).

特发此文,假装自己还没AFO。

代码

好长啊,500多B.


#include<cstdio>
#include<cstdlib>
#include<cstring>
#define llong long long
using namespace std;

const int N = 2e5;
const int P = 1e9+7;
int a[N+3],b[N+3];
llong f[N+3],g[N+3];
int n;

int main()
{
    scanf("%d",&n);
    for(int i=1; i<=n; i++) scanf("%d",&a[i]);
    int m = 0; for(int i=1; i<=n; i++) if(i==0 || a[i]!=a[i-1]) {m++; b[m] = a[i];}
    n = m; for(int i=1; i<=n; i++) a[i] = b[i];
    f[0] = 1ll; g[a[1]] = 1ll;
    for(int i=1; i<=n; i++)
    {
        f[i] = g[a[i]];
        g[a[i+1]] = (g[a[i+1]]+f[i])%P;
    }
    printf("%lld\n",f[n]);
    return 0;
}

原文地址:https://www.cnblogs.com/suncongbo/p/10545055.html

时间: 2024-10-14 09:17:52

Atcoder AGC031B Reversi (DP计数)的相关文章

ZOJ3380- Patchouli&#39;s Spell Cards(概率DP+计数)

Patchouli's Spell Cards Time Limit: 7 Seconds      Memory Limit: 65536 KB Patchouli Knowledge, the unmoving great library, is a magician who has settled down in the Scarlet Devil Mansion (紅魔館). Her specialty is elemental magic employing the seven ele

动态规划(DP计数):HDU 5116 Everlasting L

Matt loves letter L. A point set P is (a, b)-L if and only if there exists x, y satisfying: P = {(x, y), (x + 1, y), . . . , (x + a, y), (x, y + 1), . . . , (x, y + b)}(a, b ≥ 1) A point set Q is good if and only if Q is an (a, b)-L set and gcd(a, b)

HDU 4055 The King’s Ups and Downs(DP计数)

题意:国王的士兵有n个,每个人的身高都不同,国王要将他们排列,必须一高一矮间隔进行,即其中的一个人必须同时高于(或低于)左边和右边.问可能的排列数.例子有1千个,但是最多只算到20个士兵,并且20个的情况的答案已给出. 思路:是此题HDU 4055 Number String(DP计数) 的简单版,所以看此题解就行了.数量较小,可以预先算出来.要同时考虑 <><>和><><这样的两种情况. 1 #include <iostream> 2 #inc

uva 1350 - Pinary(dp+计数)

题目链接:uva 1350 - Pinary 题目大意:给出n,输出第n给Pinary Number,Pinary Number为二进制数,并且没有连续两个1相连. 解题思路:dp[i]表示到第i位有dp[i]种,于是给定n,一层循环判断dp[i]≤n的话,就输出1,并且n减掉dp[i],注意输出0的时候,不能输出前导0. #include <cstdio> #include <cstring> typedef long long ll; const int N = 50; ll

AtCoder AGC035E Develop (DP、图论、计数)

题目链接 https://atcoder.jp/contests/agc035/tasks/agc035_e 题解 没想出来最后一步DP宛如智障-- 考虑一个数\(x\notin S\)的条件是\(x\)被删除了且在\(x\)最后一次被删除之后不能再对\(x+2\)和\(x-K\)进行删除操作.也就是说\(x+2\)和\(x-K\)的最晚删除时间要比\(x\)晚.那么我们从\(x\)往\(x+2\)和\(x-K\)连边,形成的图如果有环那么这个方案就不合法,否则合法. 如果\(K\)是偶数,显然

子序列的个数(DP计数)

这个问题让我知道了动态规划除了能用来求最优解,还可以用来做计数 = = 然后,取模的时候如果有减法是这个样子取模的: (a-b)%MOD = ((a-n)%MOD+MOD)%MOD: 因为(a-b)可能会产生负数. 问题概述: 给定一个正整数序列,序列中元素的个数和元素值大小都不超过105, 求其所有子序列的个数. 注意相同的只算一次:例如 {1,2,1}有子序列{1} {2} {1,2} {2,1}和{1,2,1}.最后结果对10^9 + 7取余数. 子序列的定义:对于一个序列a=a[1],a

HDU 1978 How many ways (DP,计数)

http://acm.hdu.edu.cn/showproblem.php?pid=1978 How many ways Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 3022    Accepted Submission(s): 1771 Problem Description 这是一个简单的生存游戏,你控制一个机器人从一个棋盘的起

F - Tmutarakan Exams URAL - 1091 -莫比乌斯函数-容斥 or DP计数

F - Tmutarakan Exams 题意 : 从 < = S 的 数 中 选 出 K 个 不 同 的 数 并 且 gcd > 1 .求方案数. 思路 :记 录 一 下 每 个 数 的 倍 数 vector 存 储 ,最后从 2 开始 遍历 一遍每个数 ,从 他的倍数中 挑选 k个 组合数求解. 但是会有重复,因为 比如 K=2,S=15时 , 2倍数 : 2  ,4 , 6,  8, 10,  12, 14 ,   挑出了 这种情况 6 ,12,然后 从3的倍数 : 3, 6 ,9,12

Vijos p1770 大内密探 树形DP+计数

4天终于做出来了,没错我就是这么蒟蒻.教训还是很多的. 建议大家以后编树形DP不要用记忆化搜索,回溯转移状态个人感觉更有条理性. 大神题解传送门 by iwtwiioi 我的题解大家可以看注释"//"部分 本题我用的树形DP中dp[x][fa][need]表示编号为x的节点的父亲选(1)没选(0),x的父亲需(1)不需要(0)其他节点来覆盖. 若父亲节点选了,则need肯定为0,所以不存在fa==1而need==1的状态,相当于浪费了¼的空间.毕竟数据范围比较小,而且程序要有可读性!程