http://acm.sdut.edu.cn/sdutoj/problem.php?action=showproblem&problemid=2607

Mountain Subsequences

Time Limit: 1000ms   Memory limit: 65536K  有疑问?点这里^_^

题目描述

Coco is a beautiful ACMer girl living in a very beautiful mountain. There are many trees and flowers on the mountain, and there are many animals and birds also. Coco like the mountain so much that she now name some letter sequences as Mountain Subsequences.

A Mountain Subsequence is defined as following:

1. If the length of the subsequence is n, there should be a max value letter, and the subsequence should like this, a1 < ...< ai < ai+1 < Amax > aj > aj+1 > ... > an

2. It should have at least 3 elements, and in the left of the max value letter there should have at least one element, the same as in the right.

3. The value of the letter is the ASCII value.

Given a letter sequence, Coco wants to know how many Mountain Subsequences exist.

输入

Input contains multiple test cases.

For each case there is a number n (1<= n <= 100000) which means the length of the letter sequence in the first line, and the next line contains the letter sequence.

Please note that the letter sequence only contain lowercase letters.

输出

For each case please output the number of the mountain subsequences module 2012.

示例输入

4
abca

示例输出

4

提示

The 4 mountain subsequences are:

aba, aca, bca, abca

来源

 2013年山东省第四届ACM大学生程序设计竞赛

示例程序

分析:

给你一个长度为n的字符串仅由小写英文字母组成,求满足

a1 < ...< ai < ai+1 < Amax > aj > aj+1 > ... > an

的子串的个数,其实也就是统计所有满足以某一元素为中心左边递增,右边递减的子串的数目,要求该子串

最小长度为3,中心元素左右都至少有一个元素。

题目告诉我们输入串仅包含26个英文字母,这样我们只要枚举每一个位置,然后记录每个位置左边满足

条件的个数,右边满足条件的个数,最后乘起来就是了。关键是我们如何统计左右两边满足的个数呢?

本能的反应告诉我可以用DP来做,主要还是因为有之前做过的求最长递增子序列的基础。可是,

老师告诉我说,这不叫DP,看代码会发现,其实就是个递推求解关系式。我总是觉得,之所以能想到

这里,完全是应用了DP的阶段划分的思想,暂且不论也罢。那么,怎么划分阶段呢?我们定义

数组dp[26],dl[maxn],dr[maxn],dp[c]表示以字符c结尾的满足情况的个数,dl[i]表示第i个位置左边满足

条件的个数,dr[i]表示第i个位置右边满足条件的个数。当然,我们可以发现,dp[s[i]] = (dl[i] + 1),s[i]= c;

1表示s[i]单独一个时满足的情况,dl[i]表示他左边的满足的各种情况加上s[i] 后满足的情况。

注意:

有细心的同学会问,在一个串中如果有相同的字母,那么他们的dp值是否相同呢?答案就在题意中给出了。

题目在要求该子串的时候用了

a1 < ...< ai < ai+1 < Amax > aj > aj+1 > ... > an

这样一个式子,每个元素都表示不同位置的元素,也就是说,在串aaba中应该有aba,aba两个答案,

而不是只有aba一个。因为前面两个子串形式上看虽然相同,但纠其本质,a和a的来源不同,

可以表示为a1ba和a2ba两个答案。

AC代码:

 #include <iostream>
#include <cstring>
#define maxn 100005
#define mod 2012
using namespace std; char str[maxn];
int dp[],dl[maxn],dr[maxn],s[maxn];
int main()
{
int n;
while(cin>>n)
{
cin>>str;
for(int i=;i<n;i++)
s[i]=str[i]-'a';
memset(dp,,sizeof(dp));
memset(dl,,sizeof(dl));
memset(dr,,sizeof(dr));
for(int i=;i<n;i++)
{
for(int j=;j<s[i];j++)
dl[i]=(dl[i]+dp[j])%mod;
dp[s[i]]=(dp[s[i]]+dl[i]+)%mod;
}
memset(dp,,sizeof(dp));
for(int i=n-;i>=;i--)
{
for(int j=;j<s[i];j++)
dr[i]=(dr[i]+dp[j])%mod;
dp[s[i]]=(dp[s[i]]+dr[i]+)%mod;
}
int ans=;
for(int i=;i<n;i++)
ans=(ans+dl[i]*dr[i])%mod;
cout<<ans<<endl;
}
return ;
}

官方代码:

 #include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
const int maxn = +;
int n;
char s[maxn];
int dl[maxn], dr[maxn], dp[], cnt[];
const int mod = ;
int main() {
freopen("data.in", "r", stdin);
freopen("data.out", "w", stdout);
while(~scanf("%d", &n)) {
scanf("%s", s);
for(int i = ; i < n; i++) s[i] -= 'a';
memset(dp, , sizeof(dp));
memset(cnt, , sizeof(cnt));
memset(dl, , sizeof(dl));
memset(dr, , sizeof(dr));
for(int i = ; i < n; i++) {
for(int j = ; j < s[i]; j++) {
dl[i] += dp[j] + cnt[j];
dl[i] %= ;
}
cnt[s[i]] ++;
cnt[s[i]] %= ;
dp[s[i]] += dl[i];
dp[s[i]] %= ; } memset(dp, , sizeof(dp));
memset(cnt, , sizeof(cnt)); for(int i = n - ; i >= ; i-- ) {
for(int j = ; j < s[i]; j ++) {
dr[i] += dp[j] + cnt[j];
dr[i] %= ;
}
cnt[s[i]] ++;
cnt[s[i]] %= ;
dp[s[i]] += dr[i];
dp[s[i]] %= ;
}
int ans = ;
for(int i = ; i < n; i++) {
ans += dl[i] * dr[i] ;
ans %= ;
}
printf("%d\n", ans);
}
}

官方数据生成代码:

 #include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
const int maxn = +;
int n;
char s[maxn];
int dl[maxn], dr[maxn], dp[], cnt[];
const int mod = ;
int main() {
freopen("data.in", "r", stdin);
freopen("data.out", "w", stdout);
while(~scanf("%d", &n)) {
scanf("%s", s);
for(int i = ; i < n; i++) s[i] -= 'a';
memset(dp, , sizeof(dp));
memset(cnt, , sizeof(cnt));
memset(dl, , sizeof(dl));
memset(dr, , sizeof(dr));
for(int i = ; i < n; i++) {
for(int j = ; j < s[i]; j++) {
dl[i] += dp[j] + cnt[j];
dl[i] %= ;
}
cnt[s[i]] ++;
cnt[s[i]] %= ;
dp[s[i]] += dl[i];
dp[s[i]] %= ; } memset(dp, , sizeof(dp));
memset(cnt, , sizeof(cnt)); for(int i = n - ; i >= ; i-- ) {
for(int j = ; j < s[i]; j ++) {
dr[i] += dp[j] + cnt[j];
dr[i] %= ;
}
cnt[s[i]] ++;
cnt[s[i]] %= ;
dp[s[i]] += dr[i];
dp[s[i]] %= ;
}
int ans = ;
for(int i = ; i < n; i++) {
ans += dl[i] * dr[i] ;
ans %= ;
}
printf("%d\n", ans);
}
}

sdutoj 2607 Mountain Subsequences的更多相关文章

  1. 13年山东省赛 Mountain Subsequences(dp)

    转载请注明出处: http://www.cnblogs.com/fraud/          ——by fraud Mountain Subsequences Time Limit: 1 Sec   ...

  2. 2013年山东省赛F题 Mountain Subsequences

    2013年山东省赛F题 Mountain Subsequences先说n^2做法,从第1个,(假设当前是第i个)到第i-1个位置上哪些比第i位的小,那也就意味着a[i]可以接在它后面,f1[i]表示从 ...

  3. sdut Mountain Subsequences 2013年山东省第四届ACM大学生程序设计竞赛

    Mountain Subsequences 题目描述 Coco is a beautiful ACMer girl living in a very beautiful mountain. There ...

  4. 山东省第四届省赛 E-Mountain Subsequences

    Description Coco is a beautiful ACMer girl living in a very beautiful mountain. There are many trees ...

  5. 山东省第四届ACM省赛

    排名:http://acm.sdut.edu.cn/sd2012/2013.htm 解题报告:http://www.tuicool.com/articles/FnEZJb A.Rescue The P ...

  6. 2013山东省ICPC结题报告

    A.Rescue The Princess 已知一个等边三角形的两个顶点A.B,求第三个顶点C,A.B.C成逆时针方向. 常规的解题思路就是用已知的两个点列出x,y方程,但这样求出方程的解的表达式比较 ...

  7. 山东省第四届ACM大学生程序设计竞赛解题报告(部分)

    2013年"浪潮杯"山东省第四届ACM大学生程序设计竞赛排名:http://acm.upc.edu.cn/ranklist/ 一.第J题坑爹大水题,模拟一下就行了 J:Contes ...

  8. 山东省第四届ACM程序设计竞赛部分题解

    A : Rescue The Princess 题意: 给你平面上的两个点A,B,求点C使得A,B,C逆时针成等边三角形. 思路: http://www.cnblogs.com/E-star/arch ...

  9. [ACM]2013山东省“浪潮杯”省赛 解题报告

    题目地址:http://acm.upc.edu.cn/problemset.php?page=13  2217~2226 A.Rescue The Princess 一个等边三角形告诉前2个点,求逆时 ...

随机推荐

  1. hbase基本命令

    基本命令  建表scores  具有两个列族grad 和courese create 'scores','grade', 'course' 查看当前HBase中具有哪些表 list 查看表结构 des ...

  2. 蓝牙4.0的LM层说明

    1.概念 The Link Manager Protocol (LMP) is used to control and negotiate all aspects of the operation o ...

  3. java JDK8 学习笔记——第16章 整合数据库

    第十六章 整合数据库 16.1 JDBC入门 16.1.1 JDBC简介 1.JDBC是java联机数据库的标准规范.它定义了一组标准类与接口,标准API中的接口会有数据库厂商操作,称为JDBC驱动程 ...

  4. php日期时间函数 整理

    设定系统默认时区 date_default_timezone_get() $tz='America/Los_Angeles'; 返回系统默认时区 date_default_timezone_set($ ...

  5. 算法训练 A+B Problem

     算法训练 A+B Problem   时间限制:1.0s   内存限制:512.0MB      问题描述 输入A,B. 输出A+B. 输入格式 输入包含两个整数A,B,用一个空格分隔. 输出格式 ...

  6. 七步实现magento迁移

    很多朋友都在为magento搬家烦恼,要想把magento从一台服务器迁移到另一台服务器上并不难,下面给大家介绍一种简单方法就能轻松实现magento迁移. 范例:从http://magento.yo ...

  7. Codeforces Round #376 (Div. 2) C. Socks---并查集+贪心

    题目链接:http://codeforces.com/problemset/problem/731/C 题意:有n只袜子,每只都有一个颜色,现在他的妈妈要去出差m天,然后让他每天穿第 L 和第 R 只 ...

  8. 学习一下Fiddler的强大

    ①引言:Fiddler (中文名称:小提琴)是一个 HTTP 的调试代理,以代理服务器的方式,监听系统的Http网络数据流动, Fiddler 可以也可以让你检查所有的 HTTP 通讯,设置断点,以及 ...

  9. Java学习-035-JavaWeb_004 -- JSP include 指令

    inclue 指令是将不同的文件插入到 JSP 网页中,这些文件可以是文本文件.HTML文件.JSP 文件,指令语法如下: <%@include file="相对路径"%&g ...

  10. Java学习-014-文本文件写入实例源代码(两种写入方式)

    此文源码主要为应用 Java 读取文本文件内容实例的源代码.若有不足之处,敬请大神指正,不胜感激! 第一种:文本文件写入,若文件存在则删除原文件,并重新创建文件.源代码如下所示: /** * @fun ...